欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

synchronized与Lock的区别

程序员文章站 2024-01-08 08:52:28
...

线程与进程
一个程序最少需要一个进程,而一个进程最少需要一个线程。关系是线程->进程->程序的大致组成结构。所以线程是程序执

行流的最小单位,而进程是系统进行资源分配和调度的一个独立单位。

Thread的几个重要方法
a、start()方法,调用该方法开始执行该线程;b、stop()方法,调用该方法强制结束该线程执行;c、join方法,调用该方法

等待该线程结束。d、sleep()方法,调用该方法该线程进入等待。e、run()方法,调用该方法直接执行线程的run()方法,但

是线程调用start()方法时也会运行run()方法,区别就是一个一个是由线程调度运行run()方法,一个是直接调用了线程中的

run方法!!
wait()与notify()方法是object的方法,不是Thread的方法!!同时,wait()与notify()会配合使用,分别表示线程挂起和

线程恢复。
这里还有一个很常见的问题:wait和sleep的区别,简单来说wait()会释放对象锁 而sleep()不会释放对象锁
1、线程自旋和适应性自旋
java线程其实是映射在内核之上的,线程的挂起和恢复会极大的影响开销。并且jdk官方人员发现,很多线程在等待锁的时候

,在很短的一段时间就获得了锁,所以他们在线程等待的时候,并不需要把线程挂起,而是让他无目的的循环,一般设置10

次。这样就避免了线程切换的开销,极大的提升了性能。
而适应性自旋,是赋予了自旋一种学习能力,它并不固定自旋10次一下。他可以根据它前面线程的自旋情况,从而调整它的

自旋,甚至是不经过自旋而直接挂起。
锁消除
就是把不必要的同步在编译阶段进行移除。
锁粗化
在用synchronized的时候,我们都讲究为了避免大开销,尽量同步代码块要小。那么为什么还要加粗呢?
轻量级锁
偏向锁

1、首先synchronized是java内置关键字,在jvm层面,Lock是个java类;
2、synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
3、synchronized会自动释放锁(a线程执行完同步代码会释放锁;b线程执行过程中发生异常会释放锁),Lock需在finally中手

工释放锁(unlock()方法释放锁),否则容易造成线程死锁;
4、用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待

下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束;
5、synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可)
6、Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。
lock():获取锁,如果锁被暂用则一直等待
unlock:释放锁
tryLock():注意返回类型是boolean,如果获取锁的时候锁被占用就返回false,否则返回true
tryLock(long time,TimeUnit unit):比起tryLock()就是给了一个时间期限,保证等待参数时间
lockInterruptibly():用该锁的获得方式,如果线程在获取锁的阶段进入了等待,那么可以中断此线程,先去做别的事

package com.trx.lockdemo;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockTest {

private Lock  lock = new ReentrantLock();
/**
 * 使用完毕释放后其他线程才能获取锁
 */

public void lockTest(Thread thread){
	
	lock.lock();//获取锁
	try {
		
	   System.out.println("线程"+thread.getName()+"获取当前锁");//打印当前锁的名称

		Thread.sleep(2000);
	} catch (Exception e) {
		// TODO Auto-generated catch block
		 System.out.println("线程"+thread.getName()+"发生了异常释放锁");
	}finally{
		System.out.println("线程"+thread.getName()+"执行完毕释放锁");
		lock.unlock();
	}
}

public static void main(String[] args){
	
	final LockTest lockTest = new LockTest();
	//声明一个线程 "线程一"
	Thread thread1 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread1");
	
	Thread thread2 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"Thread2");
	
	Thread thread3 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread3");
	
	Thread thread4 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread4");
	Thread thread5 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread5");
	Thread thread6 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread6");
	thread6.start();
	thread5.start();
	thread4.start();
	thread3.start();
	thread2.start();
	thread1.start();
}

}

执行结果:
线程thread6获取当前锁
线程thread6执行完毕释放锁
线程thread4获取当前锁
线程thread4执行完毕释放锁
线程thread5获取当前锁
线程thread5执行完毕释放锁
线程thread1获取当前锁
线程thread1执行完毕释放锁
线程Thread2获取当前锁
线程Thread2执行完毕释放锁
线程thread3获取当前锁
线程thread3执行完毕释放锁

public void tryLockTest(Thread thread){
	
	if(lock.tryLock()){//尝试获取锁
		
		try {
			System.out.println("线程"+thread.getName()+"获取当前锁");//打印当前锁的名称
			Thread.sleep(2000);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("线程"+thread.getName()+"发生了异常释放锁");
		}finally{
			System.out.println("线程"+thread.getName()+"执行完毕释放锁");
			lock.unlock();//释放锁
		}
	}else{
		System.out.println("我是线程"+Thread.currentThread().getName()+"当前锁被别人占用,我

无法获取");
}
}

public static void main(String[] args){
	
	final LockTest lockTest = new LockTest();
/*	//声明一个线程 "线程一"
	Thread thread1 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread1");
	
	Thread thread2 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"Thread2");
	
	Thread thread3 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread3");
	
	Thread thread4 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread4");
	Thread thread5 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread5");
	Thread thread6 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread6");*/
	
	//声明一个线程 "线程一"
	Thread thread1 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.tryLockTest(Thread.currentThread());
		}
		
	},"thread1");
	
	Thread thread2 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.tryLockTest(Thread.currentThread());
		}
		
	},"Thread2");
	
	Thread thread3 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.tryLockTest(Thread.currentThread());
		}
		
	},"thread3");
	
	Thread thread4 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.tryLockTest(Thread.currentThread());
		}
		
	},"thread4");
	Thread thread5 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.tryLockTest(Thread.currentThread());
		}
		
	},"thread5");
	Thread thread6 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.tryLockTest(Thread.currentThread());
		}
		
	},"thread6");
	thread6.start();
	thread5.start();
	thread4.start();
	thread3.start();
	thread2.start();
	thread1.start();
}

我是线程thread6当前锁被别人占用,我无法获取
我是线程thread3当前锁被别人占用,我无法获取
我是线程thread4当前锁被别人占用,我无法获取
线程thread5获取当前锁
我是线程thread1当前锁被别人占用,我无法获取
我是线程Thread2当前锁被别人占用,我无法获取
线程thread5执行完毕释放锁

public void tryLockParamTest(Thread thread) throws InterruptedException{
	
	if(lock.tryLock(3000, TimeUnit.MILLISECONDS)){
		
		try{
		System.out.println("线程"+thread.getName()+"获取当前锁");//打印当前锁的名称
		Thread.sleep(4000);//为看出执行效果,是线程此处休眠2秒
		}catch(Exception e){
			System.out.println("线程"+thread.getName()+"发生了异常释放锁");
		}finally{
			System.out.println("线程"+thread.getName()+"执行完毕释放锁");
			lock.unlock();//释放锁
		}
	}else{
		
		System.out.println("我是线程"+Thread.currentThread().getName()+"当前锁被别人占用,等

待3s后无法获取,放弃");
}
}

public static void main(String[] args){
	
	final LockTest lockTest = new LockTest();
/*	//声明一个线程 "线程一"
	Thread thread1 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread1");
	
	Thread thread2 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"Thread2");
	
	Thread thread3 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread3");
	
	Thread thread4 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread4");
	Thread thread5 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread5");
	Thread thread6 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.lockTest(Thread.currentThread());
		}
		
	},"thread6");*/
	
	/*//声明一个线程 "线程一"
	Thread thread1 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.tryLockTest(Thread.currentThread());
		}
		
	},"thread1");
	
	Thread thread2 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.tryLockTest(Thread.currentThread());
		}
		
	},"Thread2");
	
	Thread thread3 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.tryLockTest(Thread.currentThread());
		}
		
	},"thread3");
	
	Thread thread4 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.tryLockTest(Thread.currentThread());
		}
		
	},"thread4");
	Thread thread5 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.tryLockTest(Thread.currentThread());
		}
		
	},"thread5");
	Thread thread6 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			lockTest.tryLockTest(Thread.currentThread());
		}
		
	},"thread6");*/
	
	//声明一个线程 "线程一"
	Thread thread1 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			try {
				lockTest.tryLockParamTest(Thread.currentThread());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	},"thread1");
	
	Thread thread2 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			try {
				lockTest.tryLockParamTest(Thread.currentThread());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	},"Thread2");
	
	Thread thread3 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			try {
				lockTest.tryLockParamTest(Thread.currentThread());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	},"thread3");
	
	Thread thread4 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			try {
				lockTest.tryLockParamTest(Thread.currentThread());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	},"thread4");
	Thread thread5 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			try {
				lockTest.tryLockParamTest(Thread.currentThread());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	},"thread5");
	Thread thread6 = new Thread(new Runnable(){

		public void run() {
			// TODO Auto-generated method stub
			try {
				lockTest.tryLockParamTest(Thread.currentThread());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	},"thread6");
	thread6.start();
	thread5.start();
	thread4.start();
	thread3.start();
	thread2.start();
	thread1.start();
}

线程thread5获取当前锁
我是线程Thread2当前锁被别人占用,等待3s后无法获取,放弃
我是线程thread1当前锁被别人占用,等待3s后无法获取,放弃
我是线程thread6当前锁被别人占用,等待3s后无法获取,放弃
我是线程thread3当前锁被别人占用,等待3s后无法获取,放弃
我是线程thread4当前锁被别人占用,等待3s后无法获取,放弃
线程thread5执行完毕释放锁

ReentrantReadWriteLock里面提供了很多丰富的方法,不过最主要的有两个方法:readLock()和writeLock()用来获取读锁和

写锁。假如有很多线程要同时进行读操作的话,先看一下synchronized达到的效果:
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Test {

private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
public static void main(String[] args){
	
	final Test test = new Test();
	new Thread(){
		public void run(){
			test.get(Thread.currentThread());
		}
	}.start();
	
	new Thread(){
		
		public void run(){
			test.get(Thread.currentThread());
		}
	}.start();
}

public synchronized void get(Thread thread){

	long start = System.currentTimeMillis();
	while(System.currentTimeMillis()-start<=1){
		System.out.println(thread.getName()+"正在进行读操作");
	}
	System.out.println(thread.getName()+"读操作完毕");
}

/*public void get(Thread thread){
	
	rwl.readLock().lock();
	try{
	long start = System.currentTimeMillis();
	while(System.currentTimeMillis()-start<=1){
		System.out.println(thread.getName()+"正在进行读操作");
	}
	System.out.println(thread.getName()+"读操作完毕");
	}finally{
		rwl.readLock().unlock();
	}
}*/

}

直到thread0执行完读操作之后,才会打印thread1执行读操作信息。
输出结果:
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0读操作完毕
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1读操作完毕

package com.trx.lockdemo;

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Test {

private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
public static void main(String[] args){
	
	final Test test = new Test();
	new Thread(){
		public void run(){
			test.get(Thread.currentThread());
		}
	}.start();
	
	new Thread(){
		
		public void run(){
			test.get(Thread.currentThread());
		}
	}.start();
}

/* public synchronized void get(Thread thread){

	long start = System.currentTimeMillis();
	while(System.currentTimeMillis()-start<=1){
		System.out.println(thread.getName()+"正在进行读操作");
	}
	System.out.println(thread.getName()+"读操作完毕");
}*/

public void get(Thread thread){
	
	rwl.readLock().lock();
	try{
	long start = System.currentTimeMillis();
	while(System.currentTimeMillis()-start<=1){
		System.out.println(thread.getName()+"正在进行读操作");
	}
	System.out.println(thread.getName()+"读操作完毕");
	}finally{
		rwl.readLock().unlock();
	}
}

}

thread0 和thread1同时进行读操作

Thread-0正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-1正在进行读操作
Thread-0正在进行读操作
Thread-1正在进行读操作
Thread-0正在进行读操作
Thread-1正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-0正在进行读操作
Thread-1正在进行读操作
Thread-0正在进行读操作
Thread-1正在进行读操作
Thread-0正在进行读操作
Thread-1正在进行读操作
Thread-0正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-0正在进行读操作
Thread-1正在进行读操作
Thread-0正在进行读操作
Thread-1读操作完毕
Thread-0读操作完毕

锁的相关概念介绍
1、可重入锁
如果锁具备可重入性,则称作为可重入锁。像synchronized和ReentrantLock都是可重入锁,可重入性在我看来实际上表明了

锁的分配机制:基于线程的分配,而不是基于方法调用的分配。举个简单的例子,当一个线程执行到某个synchronized方法

时,比如说method1,而在method1中会调用另外一个synchronized方法method2,此时线程不必重新去申请锁,而是可以直接

执行方法method2。
class MyClass {
public synchronized void method1() {
method2();
}

public synchronized void method2() {
     
}

}
上述代码中的两个方法method1和method2都用synchronized修饰了,假如某一时刻,线程A执行到了method1,此时线程A获取

了这个对象的锁,而由于method2也是synchronized方法,假如synchronized不具备可重入性,此时线程A需要重新申请锁。

但是这就会造成一个问题,因为线程A已经持有了该对象的锁,而又在申请获取该对象的锁,这样就会线程A一直等待永远不

会获取到的锁。

而由于synchronized和Lock都具备可重入性,所以不会发生上述现象。
可中断锁

可中断锁:顾名思义,就是可以相应中断的锁
在java中,synchronized就不是可中断锁,而Lock是可中断锁。
如果某一线程A正在执行锁中的代码,另一线程B正在等待获取该锁,可能由于等待时间过长,线程B不想等待了,想处理其他

事情,我们可以让它中断自己或者在别的线程中中断它,这种就是可中断锁。
在前面演示lockInterruptibly()的用法时已经体现了Lock的可中断性。
3、公平锁
公平锁即尽量以请求锁的顺序来获取锁。比如同是有多个线程在等待一个锁,当这个锁被释放时,等待时间最久的线程(最

先请求线程)会获得该锁,就是公平锁。
非公平锁即无法保证锁的获取是按照请求锁的顺序进行的。这样就可能导致某个或者一些线程永远获取不到锁。
在Java中,synchronized就是非公平锁,它无法保证等待的线程获取锁的顺序。
而对于ReentrantLock和ReentrantReadWriteLock,它默认情况下是非公平锁,但是可以设置为公平锁。
在ReentrantLock中定义了2个静态内部类,一个是NotFairSync,一个是FairSync,分别用来实现非公平锁和公平锁。
我们可以在创建ReentrantLock对象时,通过以下方式来设置锁的公平性:
另外在ReentrantLock类中定义了很多方法,比如:
isFair() //判断锁是否是公平锁
isLocked() //判断锁是否被任何线程获取了
isHeldByCurrentThread() //判断锁是否被当前线程获取了
hasQueuedThreads() //判断是否有线程在等待该锁
在ReentrantReadWriteLock中也有类似的方法,同样也可以设置为公平锁和非公平锁。不过要记住,

ReentrantReadWriteLock
并未实现Lock接口,它实现的是ReadWriteLock接口。
4、读写锁
读写锁将对一个资源(比如文件)的访问分成了2个锁,一个读锁和一个写锁。
正因为有了读写锁,才使得多线程之间的读操作不会发生冲突
ReadWriteLock就是读写锁,它是一个接口,ReentrantReadWriteLock实现了这个接口。
可以通过readLock()获取读锁,通过writeLock()获取写锁。

上一篇:

下一篇: