在计算机科学中,锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制。锁旨在强制实施互斥排他、并发控制策略。 锁通常需要硬件支持才能有效实施。这种支持通常采取一个或多个原子指令的形式,如"test-and-set", "fetch-and-add" or "compare-and-swap"”。这些指令允许单个进程测试锁是否空闲,如果空闲,则通过单个原子操作获取锁。
1 /**
2 * true 表示 ReentrantLock 的公平锁
3 */
4 private ReentrantLock lock = new ReentrantLock(true);
5
6 public void testFail(){
7 try {
8 lock.lock();
9 System.out.println(Thread.currentThread().getName() +"获得了锁");
10 }finally {
11 lock.unlock();
12 }
13 }
14 public static void main(String[] args) {
15 FairLockTest fairLock = new FairLockTest();
16 Runnable runnable = () -> {
17 System.out.println(Thread.currentThread().getName()+"启动");
18 fairLock.testFail();
19 };
20 Thread[] threadArray = new Thread[10];
21 for (int i=0; i<10; i++) {
22 threadArray[i] = new Thread(runnable);
23 }
24 for (int i=0; i<10; i++) {
25 threadArray[i].start();
26 }
27 }
运行结果
1Thread-1启动
2Thread-1获得了锁
3Thread-3启动
4Thread-3获得了锁
5Thread-5启动
6Thread-5获得了锁
7Thread-2启动
8Thread-2获得了锁
9Thread-4启动
10Thread-4获得了锁
11Thread-6启动
12Thread-6获得了锁
13Thread-10启动
14Thread-8启动
15Thread-10获得了锁
16Thread-9启动
17Thread-7启动
18Thread-8获得了锁
19Thread-9获得了锁
20Thread-7获得了锁
看到结果里面获得锁的顺序和线程启动顺序是一致的,这就是公平锁。
new ReentrantLock(false);
运行结果 1Thread-1启动
2Thread-0启动
3Thread-2启动
4Thread-3启动
5Thread-4启动
6Thread-8启动
7Thread-7启动
8Thread-6启动
9Thread-1获得了锁
10Thread-0获得了锁
11Thread-5启动
12Thread-5获得了锁
13Thread-2获得了锁
14Thread-3获得了锁
15Thread-4获得了锁
16Thread-8获得了锁
17Thread-7获得了锁
18Thread-6获得了锁
19Thread-9启动
20Thread-9获得了锁
线程启动顺序是1、0、2、3、 4、 8 、7 、6 、5 、9,获得锁的顺序却是1 、0 、5 、2 、3 、4 、8 、7 、6 、9,这就是非公平锁,它不保证先排队尝试去获取锁的线程一定能先拿到锁。
1public class ReentrantLockTest {
2
3
4 public static void main(String[] args){
5 for (int i = 0; i < 10; i++) {
6 new Thread(() -> A()).start();
7 }
8 }
9 public static synchronized void A(){
10 System.out.println(Thread.currentThread().getName());
11 B();
12 }
13 public static synchronized void B(){
14 System.out.println(Thread.currentThread().getName());
15 }
16}
输出:
1Thread-1
2Thread-1
3Thread-0
4Thread-0
A方法和B方法同时输出了线程名称,表明即使递归使用synchronized也没有发生死锁,证明其是可重入的。
百度百科定义的读写锁是:
读写锁实际是一种特殊的自旋锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。
分段锁其实是一种锁的设计,并不是具体的一种锁,对jdk1.7 及以前的ConcurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效的并发操作。分段锁的设计目的是细化锁的粒度,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作。
在Java中,自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU。
这三种锁是指锁的状态,并且是针对Synchronized。在Java 5通过引入锁升级的机制来实现高效Synchronized。这三种锁的状态是通过对象监视器在对象头中的字段来表明的。