线程锁
0x01 synchronized
原理
synchronized是java中的一个关键字,用于实现线程同步。它的原理是使用对象监视器(monitor)来实现线程同步。
当一个线程访问被synchronized修饰的代码块或方法时,它会先获取对象的监视器,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到监视器为止。
在代码块或方法执行完毕后,线程会释放监视器,其他等待的线程可以获取监视器并进入代码块或方法执行。
使用
- 对象锁:使用synchronized修饰的方法或代码块,表示对当前对象的锁。
- 类锁:使用synchronized修饰的静态方法或代码块,表示对当前类的锁。
- 锁的释放:synchronized修饰的代码块或方法执行完毕后,会自动释放锁。
- 锁的粒度:synchronized修饰的代码块或方法可以控制对对象的锁粒度,也可以控制对类的锁粒度。
- 锁的升级和降级: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修饰的代码块或方法时,它会先获取锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
在代码块或方法执行完毕后,线程会释放锁,其他等待的线程可以获取锁并进入代码块或方法执行。
使用
- 创建ReentrantLock对象:可以使用new ReentrantLock()来创建一个ReentrantLock对象。
- 获取锁:可以使用lock()方法来获取锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
- 释放锁:可以使用unlock()方法来释放锁,在代码块或方法执行完毕后,需要手动调用unlock()方法来释放锁。
- 等待:可以使用Condition对象的await()方法来等待,线程会进入等待状态,直到被唤醒。
- 唤醒:可以使用Condition对象的signal()方法来唤醒等待的线程。
ReentrantReadWriteLock
ReentrantReadWriteLock是java中的一个类,用于实现读写锁。它的原理是使用AQS(AbstractQueuedSynchronizer)来实现线程同步。
当一个线程访问被ReentrantReadWriteLock修饰的代码块或方法时,它会先获取锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
在代码块或方法执行完毕后,线程会释放锁,其他等待的线程可以获取锁并进入代码块或方法执行。
使用
- 创建ReentrantReadWriteLock对象:可以使用new ReentrantReadWriteLock()来创建一个ReentrantReadWriteLock对象。
- 获取读锁:可以使用readLock().lock()方法来获取读锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
- 释放读锁:可以使用readLock().unlock()方法来释放读锁,在代码块或方法执行完毕后,需要手动调用unlock()方法来释放锁。
- 获取写锁:可以使用writeLock().lock()方法来获取写锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
- 释放写锁:可以使用writeLock().unlock()方法来释放写锁,在代码块或方法执行完毕后,需要手动调用unlock()方法来释放锁。
ReadWriteLock
ReadWriteLock是java中的一个接口,用于实现读写锁。它的原理是使用AQS(AbstractQueuedSynchronizer)来实现线程同步。
当一个线程访问被ReadWriteLock修饰的代码块或方法时,它会先获取锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
在代码块或方法执行完毕后,线程会释放锁,其他等待的线程可以获取锁并进入代码块或方法执行。
使用
- 创建ReadWriteLock对象:可以使用new ReentrantReadWriteLock()来创建一个ReadWriteLock对象。
- 获取读锁:可以使用ReadWriteLock对象的readLock().lock()方法来获取读锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
- 释放读锁:可以使用ReadWriteLock对象的readLock().unlock()方法来释放读锁,在代码块或方法执行完毕后,需要手动调用unlock()方法来释放锁。
- 获取写锁:可以使用ReadWriteLock对象的writeLock().lock()方法来获取写锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
- 释放写锁:可以使用ReadWriteLock对象的writeLock().unlock()方法来释放写锁,在代码块或方法执行完毕后,需要手动调用unlock()方法来释放锁。
LockSupport
LockSupport是java中的一个类,用于实现线程同步。它的原理是使用Unsafe类来实现线程同步。
当一个线程访问被LockSupport修饰的代码块或方法时,它会先获取锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
在代码块或方法执行完毕后,线程会释放锁,其他等待的线程可以获取锁并进入代码块或方法执行。
使用
- 创建LockSupport对象:可以使用new LockSupport()来创建一个LockSupport对象。
- 获取锁:可以使用LockSupport对象的park()方法来获取锁,如果获取成功,则进入代码块或方法执行;如果获取失败,则进入等待状态,直到获取到锁为止。
- 释放锁:可以使用LockSupport对象的unpark()方法来释放锁,在代码块或方法执行完毕后,需要手动调用unpark()方法来释放锁。
- 等待:可以使用LockSupport对象的park()方法来等待,线程会进入等待状态,直到被唤醒。
- 唤醒:可以使用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