1.lock锁和synchronized锁的区别
1:Synchronized 是Java的一个关键字,而Lock是java.util.concurrent.Locks 包下的一个接口;
2:Synchronized 使用过后,会自动释放锁,而Lock需要手动上锁、手动释放锁;(粒度可控)
3:Lock提供了更多的实现方法,而且可响应中断、可定时, 而synchronized 关键字不能响应中断;
4:synchronized关键字是非公平锁,即,不能保证等待锁的那些线程们的顺序,而Lock的子类ReentrantLock默认是非公平锁,但是可通过一个布尔参数的构造方法实例化出一个公平锁;
5:synchronized无法判断是否已经获取到锁,而Lock通过tryLock()方法可以判断是否已获取到锁;
6:Lock可以通过分别定义读写锁提高多个线程读操作的效率。
7:二者的底层实现不一样,synchronized是同步阻塞,采用的是悲观并发策略;Lock是同步非阻塞,采用的是乐观并发策略
PS:
公平锁与非公平锁:
公平锁就是:先等待的线程,先获得锁。 非公平锁就是:不能够保证 等待锁的 那些线程们的顺序, 公平锁因为需要维护一个等待锁资源的队列,所以性能相对低下
2.乐观锁和悲观锁的区别
悲观锁的思想是"先悲观地认为会发生冲突",在访问数据之前会将其锁定,直到操作完成后才会释放锁。确保在整个数据访问过程中,只有一个线程或进程能够访问数据,其他的线程或进程需要等待。
乐观锁的思想是"先乐观地认为不会发生冲突",在访问数据时不加锁,而在数据更新时进行冲突检测。多个线程或进程可以同时访问数据,但在提交更新时,会检查是否有其他线程或进程对数据进行了修改。如果发现冲突,就进行处理。乐观锁一般会使用版本号机制和CAS算法实现。通过版本号一致与否,即给数据加上版本,来同步更新数据以及加上版本号。
总的来说,悲观锁是先锁定资源再进行操作,保证数据的一致性,但并发性较差;而乐观锁是先进行操作再检查冲突,允许多个线程或进程同时访问,但是在更新的时候会判断一下在此期间其他线程或进程有没有去更新这个数据,可以使用版本号机制和CAS算法实现。选择使用哪种锁取决于具体的场景和需求。
3.synchronized锁的升级过程
- 无锁状态(Unlocked):当一个线程访问一个同步代码块时,并没有其他线程正在访问该代码块,那么该线程可以直接获取锁。
- 偏向锁状态(Biased):当一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价。
- 轻量级锁状态(Lightweight):当锁是偏向锁的时候,被另外的线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,从而提高性能。
- 重量级锁状态(Heavyweight):当轻量级锁外的其他线程自旋超过一定的次数,或者一个线程在持有锁,一个在自旋,又有第三个来访时,轻量级锁就升级为重量级锁。
4.countDownLatch的三个方法
- CountDownLatch(int count); //构造方法,创建一个值为count 的计数器。