线程锁

  1. 0x01 synchronized
    1. 原理
  2. 0x02 java.concurrent.locks.Lock
    1. ReentrantLock 和 Condition
    2. ReentrantReadWriteLock
    3. ReadWriteLock
    4. LockSupport

0x01 synchronized

原理

synchronized是java中的一个关键字,用于实现线程同步。它的原理是使用对象监视器(monitor)来实现线程同步。

当一个线程访问被synchronized修饰的代码块或方法时,它会先获取对象的监视器,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到监视器为止。

在代码块或方法执行完毕后,线程会释放监视器,其他等待的线程可以获取监视器并进入代码块或方法执行。

使用

  1. 对象锁:使用synchronized修饰的方法或代码块,表示对当前对象的锁。
  2. 类锁:使用synchronized修饰的静态方法或代码块,表示对当前类的锁。
  3. 锁的释放:synchronized修饰的代码块或方法执行完毕后,会自动释放锁。
  4. 锁的粒度:synchronized修饰的代码块或方法可以控制对对象的锁粒度,也可以控制对类的锁粒度。
  5. 锁的升级和降级:synchronized修饰的代码块或方法可以升级为ReentrantLock,可以控制锁的粒度,可以控制锁的升级和降级。

0x02 java.concurrent.locks.Lock

locks包下有4个类,分别是:ReentrantLock、ReentrantReadWriteLock、Condition、ReadWriteLock。

ReentrantLock 和 Condition

ReentrantLock是java中的一个类,用于实现线程同步。它的原理是使用AQS(AbstractQueuedSynchronizer)来实现线程同步。

当一个线程访问被ReentrantLock修饰的代码块或方法时,它会先获取锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。

在代码块或方法执行完毕后,线程会释放锁,其他等待的线程可以获取锁并进入代码块或方法执行。

Condition是java中的一个接口,用于实现线程同步。它的原理是使用AQS(AbstractQueuedSynchronizer)来实现线程同步。

当一个线程访问被Condition修饰的代码块或方法时,它会先获取锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。

在代码块或方法执行完毕后,线程会释放锁,其他等待的线程可以获取锁并进入代码块或方法执行。

使用

  1. 创建ReentrantLock对象:可以使用new ReentrantLock()来创建一个ReentrantLock对象。
  2. 获取锁:可以使用lock()方法来获取锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
  3. 释放锁:可以使用unlock()方法来释放锁,在代码块或方法执行完毕后,需要手动调用unlock()方法来释放锁。
  4. 等待:可以使用Condition对象的await()方法来等待,线程会进入等待状态,直到被唤醒。
  5. 唤醒:可以使用Condition对象的signal()方法来唤醒等待的线程。

ReentrantReadWriteLock

ReentrantReadWriteLock是java中的一个类,用于实现读写锁。它的原理是使用AQS(AbstractQueuedSynchronizer)来实现线程同步。

当一个线程访问被ReentrantReadWriteLock修饰的代码块或方法时,它会先获取锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。

在代码块或方法执行完毕后,线程会释放锁,其他等待的线程可以获取锁并进入代码块或方法执行。

使用

  1. 创建ReentrantReadWriteLock对象:可以使用new ReentrantReadWriteLock()来创建一个ReentrantReadWriteLock对象。
  2. 获取读锁:可以使用readLock().lock()方法来获取读锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
  3. 释放读锁:可以使用readLock().unlock()方法来释放读锁,在代码块或方法执行完毕后,需要手动调用unlock()方法来释放锁。
  4. 获取写锁:可以使用writeLock().lock()方法来获取写锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
  5. 释放写锁:可以使用writeLock().unlock()方法来释放写锁,在代码块或方法执行完毕后,需要手动调用unlock()方法来释放锁。

ReadWriteLock

ReadWriteLock是java中的一个接口,用于实现读写锁。它的原理是使用AQS(AbstractQueuedSynchronizer)来实现线程同步。

当一个线程访问被ReadWriteLock修饰的代码块或方法时,它会先获取锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。

在代码块或方法执行完毕后,线程会释放锁,其他等待的线程可以获取锁并进入代码块或方法执行。

使用

  1. 创建ReadWriteLock对象:可以使用new ReentrantReadWriteLock()来创建一个ReadWriteLock对象。
  2. 获取读锁:可以使用ReadWriteLock对象的readLock().lock()方法来获取读锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
  3. 释放读锁:可以使用ReadWriteLock对象的readLock().unlock()方法来释放读锁,在代码块或方法执行完毕后,需要手动调用unlock()方法来释放锁。
  4. 获取写锁:可以使用ReadWriteLock对象的writeLock().lock()方法来获取写锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
  5. 释放写锁:可以使用ReadWriteLock对象的writeLock().unlock()方法来释放写锁,在代码块或方法执行完毕后,需要手动调用unlock()方法来释放锁。

LockSupport

LockSupport是java中的一个类,用于实现线程同步。它的原理是使用Unsafe类来实现线程同步。

当一个线程访问被LockSupport修饰的代码块或方法时,它会先获取锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。

在代码块或方法执行完毕后,线程会释放锁,其他等待的线程可以获取锁并进入代码块或方法执行。

使用

  1. 创建LockSupport对象:可以使用new LockSupport()来创建一个LockSupport对象。
  2. 获取锁:可以使用LockSupport对象的park()方法来获取锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
  3. 释放锁:可以使用LockSupport对象的unpark()方法来释放锁,在代码块或方法执行完毕后,需要手动调用unpark()方法来释放锁。
  4. 等待:可以使用LockSupport对象的park()方法来等待,线程会进入等待状态,直到被唤醒。
  5. 唤醒:可以使用LockSupport对象的unpark()方法来唤醒等待的线程。

文章标题:线程锁

本文作者:zhu8fei

发布时间:2024-08-14, 11:42:51

最后更新:2024-08-15, 09:37:02

原始链接:http://www.zhu8fei.com/2024/08/14/thread-lock.html

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 zhu8fei@163.com

目录
×

喜欢就点赞,疼爱就打赏