Java多线程——锁_阿里云,服务器

  • Java多线程——锁_阿里云,服务器已关闭评论
  • 119 人浏览
  • A+
所属分类:首页

Java多线系列文章是Java多线程的详解引见,对多线程还不熟习的同砚能够先去看一下我的这篇博客Java基本系列3:多线程超细致总结,这篇博客从宏观层面引见了多线程的团体概略,接下来的几篇文章是对多线程的深切理会。

 

Lock锁

1、简介

1、从Java5入手下手,Java供应了一种功用更壮大的线程同步机制——经由过程显式定义同步锁对象来完成同步,在这类机制下,同步锁由Lock对象充任。

2、Lock 供应了比synchronized要领和synchronized代码块更普遍的锁定操纵,Lock许可完成更天真的构造,能够具有差异很大的属性,而且支撑多个相干的Condition对象。

3、Lock是掌握多个线程对同享资源举行接见的东西。一般,锁供应了对同享资源的独有接见,每次只能有一个线程对Lock对象加锁,线程入手下手接见同享资源之前应先取得Lock对象。

4、某些锁大概许可对同享资源并发接见,如ReadWriteLock(读写锁),Lock、ReadWriteLock是Java5供应的两个根接口,并为Lock 供应了ReentrantLock(可重入锁)完成类,为ReadWriteLock供应了ReentrantReadWriteLock 完成类。

5、Java8新增了新型的StampedLock类,在大多数场景中它能够替换传统的ReentrantReadWriteLock。ReentrantReadWriteLock 为读写操纵供应了三种锁形式:Writing、ReadingOptimistic、Reading。

 

Java多线程——锁_阿里云,服务器

 

2、Lock锁运用

class X{
	//定义锁对象
	private final ReentrantLock lock=new ReentrantLock();
	
	//定义须要保证线程平安的要领
	public void m() {
		//加锁
		lock.lock();
		try {
			//须要保证线程平安的代码
		}
		finally {
			lock.unlock();
		}
	}
}

  

 

ReentranLock  

1、简介

在Java多线程中,能够运用synchronized关键字来完成线程之间同步互斥,但在JDK1.5中新增加了ReentrantLock类也能到达一样的效果,而且在扩大功用上也越发壮大,比方具有嗅探锁定、多路分支关照等功用,而且在运用上也比synchronized越发的天真。

 

2、运用ReentranLock完成同步

既然ReentrantLock类在功用上比拟synchronized更多,那末就以一个开端的递次示例来引见一下ReentrantLock类的运用。

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

class MyService{
	private Lock lock=new ReentrantLock();
	
	public void testMethod() {
		lock.lock();
		for(int i=0;i<5;i++) {
			System.out.println("ThreadName= "+Thread.currentThread().getName()+(" "+(i+1)));
		}
		lock.unlock();
	}
}

class MyThread extends Thread{
	private MyService service;
	
	public MyThread(MyService service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		service.testMethod();
	}
}



public class LockTest {
	
	public static void main(String[] args) {
		MyService service=new MyService();
		MyThread t1=new MyThread(service);
		MyThread t2=new MyThread(service);
		MyThread t3=new MyThread(service);
		MyThread t4=new MyThread(service);
		MyThread t5=new MyThread(service);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
		
	}

}

  

运转效果:

ThreadName= Thread-2 1
ThreadName= Thread-2 2
ThreadName= Thread-2 3
ThreadName= Thread-2 4
ThreadName= Thread-2 5
ThreadName= Thread-0 1
ThreadName= Thread-0 2
ThreadName= Thread-0 3
ThreadName= Thread-0 4
ThreadName= Thread-0 5
ThreadName= Thread-3 1
ThreadName= Thread-3 2
ThreadName= Thread-3 3
ThreadName= Thread-3 4
ThreadName= Thread-3 5
ThreadName= Thread-4 1
ThreadName= Thread-4 2
ThreadName= Thread-4 3
ThreadName= Thread-4 4
ThreadName= Thread-4 5
ThreadName= Thread-1 1
ThreadName= Thread-1 2
ThreadName= Thread-1 3
ThreadName= Thread-1 4
ThreadName= Thread-1 5

  

从运转的效果来看,当前线程打印终了以后将锁举行开释,其他线程才够继承打印。线程打印的数据是分组打印,由于当前线程已持有锁,但线程之间打印的递次是随机的。lock.lock()是对当前线程加锁,当线程实行终了后挪用lock.unlock()开释锁,这时候其他线程能够去猎取锁,至因而哪个线程能够争抢到锁照样看CPU的调理

 

3、运用Condition完成守候/关照:毛病用法与处理

关键字synchronized与wait()和notify()/notifyAll()要领相连系能够完成守候/关照形式,类ReentrantLock也能够完成一样的功用,但须要借助于Condition对象。Condition类是在JDK5中涌现的手艺,运用它有更好的天真性,比方能够完成多路关照功用,也就是在一个Lock对象内里能够建立多个Condition(即对象监视器)实例,线程对象能够注册在指定的Condition中,从而能够有挑选性地举行线程关照,在调理线程上越发天真。

在运用notify(O/notifyAll0要领举行关照时,被关照的线程倒是由JVM随机挑选的。但运用ReentrantLock连系Condition类是能够完成前面引见过的“挑选性关照”,这个功用黑白常重要的,而且在Condition类中是默许供应的。

而synchronized就相当于全部Lock对象中只要一个单一的Condition对象,一切的线程都注册在它一个对象的身上。线程入手下手notifyAll()时,须要关照一切的WAITING线程,没有挑选权,会涌现相当大的效力问题。

 

package Thread05;

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

class MyService{
	private Lock lock=new ReentrantLock();
	private Condition condition=lock.newCondition();
	public void await() {
		try {
			lock.lock();
			System.out.println("A");
			condition.await();
			System.out.println("B");
		}catch(InterruptedException e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
			System.out.println("锁开释了");
		}
	}
}

class MyThread extends Thread{
	private MyService service;
	
	public MyThread(MyService service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		service.await();
	}
}



public class LockTest {
	
	public static void main(String[] args) {
		MyService service=new MyService();
		MyThread thread=new MyThread(service);
		thread.start();
		
	}

}

  

输出效果:

A

  

我们能够看到输出效果只要一个A,并没有其他的输出,这是由于挪用Condition的await()要领,使当前实行使命的线程进入了守候的状况

注重:在运用Condition要领时要先挪用lock.lock()代码取得同步监视器

 

4、准确运用Condition完成守候/关照

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

class MyService{
	private Lock lock=new ReentrantLock();
	private Condition condition=lock.newCondition();
	public void await() {
		try {
			lock.lock();
			System.out.println("await时候为"+System.currentTimeMillis());
			condition.await();
		}catch(InterruptedException e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
			System.out.println("锁开释了");
		}
	}
	
	public void signal() {
		try {
			lock.lock();
			System.out.println("signal时候为"+System.currentTimeMillis());
			condition.signal();
		}finally {
			lock.unlock();
		}
	}
}

class MyThread extends Thread{
	private MyService service;
	
	public MyThread(MyService service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		service.await();
	}
}


public class LockTest {
	
	public static void main(String[] args) throws InterruptedException {
		MyService service=new MyService();
		MyThread thread=new MyThread(service);
		thread.start();
		Thread.sleep(3000);
		service.signal();
		
	}

}

  

运转效果:

await时候为1575599786039
signal时候为1575599789051
锁开释了

  

胜利完成守候/关照形式

Object类中的wait()要领相当于Condition类中的await()要领,Object类中的wait(long timeout)要领相当于Condition类中的await(long time,TimeUnit unit)要领。Object类中的notify()要领相当于Condition类中的signal()要领。Object类中的notifyAll()要领相当于Condition类中的signalAll()要领。

 

5、运用多个Condition完成关照一切线程

前面运用一个Condition对象来完成守候/关照形式,实在Condition对象也能够建立多个。那末一个Condition对象和多个Condition对象在运用上有什么区别呢?

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

class MyService{
	private Lock lock=new ReentrantLock();
	private Condition condition=lock.newCondition();
	public void awaitA() {
		try {
			lock.lock();
			System.out.println("begin awaitA时候为"+System.currentTimeMillis()+"ThreadName"+Thread.currentThread().getName());
			condition.await();
			System.out.println("end awaitA时候为"+System.currentTimeMillis()+"ThreadName"+Thread.currentThread().getName());
		}catch(InterruptedException e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
	
	public void awaitB() {
		try {
			lock.lock();
			System.out.println("begin awaitB时候为"+System.currentTimeMillis()+"ThreadName"+Thread.currentThread().getName());
			condition.await();
			System.out.println("end awaitB时候为"+System.currentTimeMillis()+"ThreadName"+Thread.currentThread().getName());
		}catch(InterruptedException e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
	
	public void signalAll() {
		try {
			lock.lock();
			System.out.println("signalAll时候为"+System.currentTimeMillis());
			condition.signalAll();
		}finally {
			lock.unlock();
		}
	}
}

class MyThreadA extends Thread{
	private MyService service;
	
	public MyThreadA(MyService service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		service.awaitA();
	}
}

class MyThreadB extends Thread{
private MyService service;
	
	public MyThreadB(MyService service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		service.awaitB();
	}
}


public class LockTest {
	
	public static void main(String[] args) throws InterruptedException {
		MyService service=new MyService();
		MyThreadA threadA=new MyThreadA(service);
		threadA.setName("A");
		threadA.start();
		MyThreadB threadB=new MyThreadB(service);
		threadB.setName("B");
		threadB.start();
		Thread.sleep(3000);
		service.signalAll();
	}

}

  

运转效果:

begin awaitA时候为1575600904529ThreadNameA
begin awaitB时候为1575600904545ThreadNameB
signalAll时候为1575600907537
end awaitA时候为1575600907537ThreadNameA
end awaitB时候为1575600907537ThreadNameB

  

6、运用多个Condition完成关照部份线程

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

class MyService{
	private Lock lock=new ReentrantLock();
	private Condition conditionA=lock.newCondition();
	private Condition conditionB=lock.newCondition();
	public void awaitA() {
		try {
			lock.lock();
			System.out.println("begin awaitA时候为"+System.currentTimeMillis()+"ThreadName"+Thread.currentThread().getName());
			conditionA.await();
			System.out.println("end awaitA时候为"+System.currentTimeMillis()+"ThreadName"+Thread.currentThread().getName());
		}catch(InterruptedException e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
	
	public void awaitB() {
		try {
			lock.lock();
			System.out.println("begin awaitB时候为"+System.currentTimeMillis()+"ThreadName"+Thread.currentThread().getName());
			conditionB.await();
			System.out.println("end awaitB时候为"+System.currentTimeMillis()+"ThreadName"+Thread.currentThread().getName());
		}catch(InterruptedException e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
	
	//关照A
	public void signalAll_A() {
		try {
			lock.lock();
			System.out.println("signalAll_A时候为"+System.currentTimeMillis()+"ThreadName="+Thread.currentThread().getName());
			conditionA.signalAll();
		}finally {
			lock.unlock();
		}
	}
	
	//关照B
	public void signalAll_B() {
		try {
			lock.lock();
			System.out.println("signalAll_A时候为"+System.currentTimeMillis()+"ThreadName="+Thread.currentThread().getName());
			conditionA.signalAll();
		}finally {
			lock.unlock();
		}
	}
}

class MyThreadA extends Thread{
	private MyService service;
	
	public MyThreadA(MyService service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		service.awaitA();
	}
}

class MyThreadB extends Thread{
private MyService service;
	
	public MyThreadB(MyService service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		service.awaitB();
	}
}


public class LockTest {
	
	public static void main(String[] args) throws InterruptedException {
		MyService service=new MyService();
		MyThreadA threadA=new MyThreadA(service);
		threadA.setName("A");
		threadA.start();
		MyThreadB threadB=new MyThreadB(service);
		threadB.setName("B");
		threadB.start();
		Thread.sleep(3000);
		service.signalAll_A();
	}

}

  

运转效果:

begin awaitA时候为1575601785167ThreadNameA
begin awaitB时候为1575601785167ThreadNameB
signalAll_A时候为1575601788181ThreadName=main
end awaitA时候为1575601788181ThreadNameA

  

上面的代码完成关照部份线程,定义了两个Condition,在测试类中只是唤醒了A,从输出效果能够看出,线程A被唤醒了,线程B依旧处于守候状况

 

7、完成生产者/消耗者形式:一个生产者一个消耗者

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

class MyService{
	private Lock lock=new ReentrantLock();
	private Condition condition=lock.newCondition();
	private boolean hasValue=false;
	public void set() {
		try {
			lock.lock();
			while(hasValue==true) {
				condition.await();
			}
			System.out.println("打印★");
			hasValue=true;
			condition.signal();
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
	
	public void get() {
		try {
			lock.lock();
			while(hasValue==false) {
				condition.await();
			}
			System.out.println("打印☆");
			hasValue=false;
			condition.signal();
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
}

class MyThreadA extends Thread{
	private MyService service;
	
	public MyThreadA(MyService service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		for(int i=0;i<Integer.MAX_VALUE;i++) {
			service.set();	
		}
		
	}
}

class MyThreadB extends Thread{
private MyService service;
	
	public MyThreadB(MyService service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		for(int i=0;i<Integer.MAX_VALUE;i++) {
			service.get();	
		}
	}
}


public class LockTest {
	
	public static void main(String[] args) throws InterruptedException {
		MyService service=new MyService();
		MyThreadA a=new MyThreadA(service);
		a.start();
		MyThreadB b=new MyThreadB(service);
		b.start();
	}

}

  

运转效果:

Java多线程——锁_阿里云,服务器

 

 

 上面代码完成了生产者消耗者的功用,一个生产一个消耗,假如hasValue=false相当于生产者没有生产产物,当前没有可消耗的产物,所以挪用生产者生产,当hasValue=true申明当前有产物还没有被消耗,那末生产者应当住手生产,挪用消耗者消耗

 

8、完成生产者/消耗者形式:多个生产者多个消耗者

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

class MyService{
	private Lock lock=new ReentrantLock();
	private Condition condition=lock.newCondition();
	private boolean hasValue=false;
	public void set() {
		try {
			lock.lock();
			while(hasValue==true) {
				System.out.println("有大概★★一连");
				condition.await();
			}
			System.out.println("打印★");
			hasValue=true;
			condition.signal();
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
	
	public void get() {
		try {
			lock.lock();
			while(hasValue==false) {
				System.out.println("有大概☆☆一连");
				condition.await();
			}
			System.out.println("打印☆");
			hasValue=false;
			condition.signal();
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
}

class MyThreadA extends Thread{
	private MyService service;
	
	public MyThreadA(MyService service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		for(int i=0;i<Integer.MAX_VALUE;i++) {
			service.set();	
		}
		
	}
}

class MyThreadB extends Thread{
private MyService service;
	
	public MyThreadB(MyService service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		for(int i=0;i<Integer.MAX_VALUE;i++) {
			service.get();	
		}
	}
}


public class LockTest {
	
	public static void main(String[] args) throws InterruptedException {
		MyService service=new MyService();
		MyThreadA[] threadA=new MyThreadA[10];
		MyThreadB[] threadB=new MyThreadB[10];
		for(int i=0;i<10;i++) {
			threadA[i]=new MyThreadA(service);
			threadB[i]=new MyThreadB(service);
			threadA[i].start();
			threadB[i].start();
		}
	}

}

  

运转效果:

Java多线程——锁_阿里云,服务器

 

 

 运转递次后涌现了假死,由于涌现了生产者开释生产者或许消耗者开释消耗者的状况,那末该怎样处理这个问题呢?在运用synchronized完成生产者消耗者的时候我们也遇到过这类状况,当时是运用notifyAll()来处理这个问题的,那末如今运用锁我们则用signalAll()要领来处理死锁问题,将上述代码中signal()要领改成signalAll()即可

修改后递次运转效果以下

Java多线程——锁_阿里云,服务器

 

 

 递次一向一般运转,没有涌现死锁状况

 

9、平正锁和非平正锁

平正与非平正锁:锁Lock分为“平正锁”和“非平正锁”,平正锁示意线程猎取锁的递次是根据线程加锁的递次来分派的,即先来先得的FIFO先进先出递次。而非平正锁就是一种猎取锁的抢占机制,是随机取得锁的,和平正锁不一样的就是先来的不一定先获得锁,这个体式格局大概形成某些线程一向拿不到锁,效果也就是不平正的了。

建立平正锁和非平正锁ReentrantLock lock=new ReentrantLock(boolean a),建立锁时假如a为true的话,则建立的是平正锁,假如a为false的话,则建立的黑白平正锁

 

平正锁

import java.util.concurrent.locks.ReentrantLock;

class Service{
	private ReentrantLock lock;
	public Service(boolean isFair) {
		lock=new ReentrantLock(isFair);
	}
	
	public void serviceMethod() {
		try {
			lock.lock();
			System.out.println("ThreadName="+Thread.currentThread().getName()+"取得锁定");
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
}




public class LockTest {
	
	public static void main(String[] args) throws InterruptedException {
		final Service service=new Service(true);
		Runnable runnable=new Runnable() {
			
			@Override
			public void run() {
				System.out.println("★线程"+Thread.currentThread().getName()+"运转了");
				service.serviceMethod();
			}
		};
		Thread[] threadArray=new Thread[10];
		for(int i=0;i<10;i++) {
			threadArray[i]=new Thread(runnable);
		}
		for(int i=0;i<10;i++) {
			threadArray[i].start();
		}
		
	}

}

  

运转效果:

★线程Thread-2运转了
★线程Thread-3运转了
★线程Thread-0运转了
★线程Thread-9运转了
★线程Thread-4运转了
★线程Thread-8运转了
★线程Thread-5运转了
★线程Thread-1运转了
★线程Thread-6运转了
★线程Thread-7运转了
ThreadName=Thread-2取得锁定
ThreadName=Thread-6取得锁定
ThreadName=Thread-1取得锁定
ThreadName=Thread-8取得锁定
ThreadName=Thread-0取得锁定
ThreadName=Thread-7取得锁定
ThreadName=Thread-5取得锁定
ThreadName=Thread-3取得锁定
ThreadName=Thread-9取得锁定
ThreadName=Thread-4取得锁定

  

效果显现输出基本是呈有序的状况,这就是平正锁的特性

 

非平正锁

import java.util.concurrent.locks.ReentrantLock;

class Service{
	private ReentrantLock lock;
	public Service(boolean isFair) {
		lock=new ReentrantLock(isFair);
	}
	
	public void serviceMethod() {
		try {
			lock.lock();
			System.out.println("ThreadName="+Thread.currentThread().getName()+"取得锁定");
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
}




public class LockTest {
	
	public static void main(String[] args) throws InterruptedException {
		final Service service=new Service(false);
		Runnable runnable=new Runnable() {
			
			@Override
			public void run() {
				System.out.println("★线程"+Thread.currentThread().getName()+"运转了");
				service.serviceMethod();
			}
		};
		Thread[] threadArray=new Thread[10];
		for(int i=0;i<10;i++) {
			threadArray[i]=new Thread(runnable);
		}
		for(int i=0;i<10;i++) {
			threadArray[i].start();
		}
		
	}

}

  

运转效果:

★线程Thread-2运转了
★线程Thread-9运转了
★线程Thread-7运转了
★线程Thread-0运转了
★线程Thread-3运转了
★线程Thread-1运转了
★线程Thread-6运转了
★线程Thread-5运转了
★线程Thread-4运转了
ThreadName=Thread-1取得锁定
★线程Thread-8运转了
ThreadName=Thread-8取得锁定
ThreadName=Thread-2取得锁定
ThreadName=Thread-7取得锁定
ThreadName=Thread-5取得锁定
ThreadName=Thread-3取得锁定
ThreadName=Thread-4取得锁定
ThreadName=Thread-9取得锁定
ThreadName=Thread-0取得锁定
ThreadName=Thread-6取得锁定

  

非平正锁的运转效果基本上是乱序的,申明先start()启动的线程不代表先取得锁

 

10、ReentranLock要领概述:

(1)、int getHoldCount()

  getHoldCount()的作用是查询当前线程坚持此锁定的个数,也就是挪用lock()要领的次数。

 

(2)、int getQueueLength()

  getQueueLength()的作用是返回正守候猎取此锁定的线程估计数,比方有5个线程,1个线程起首实行awai()要领,那末在挪用getQueueLength()要领后返回值是4,申明有4个线程同时在守候lock的开释。

 

(3)、int getWaitQueueLength(Condition condition)

  getWaitQueueLength(Condition condition)的作用是返回守候与此锁定相干的给定前提Condition的线程估计数,比方有5个线程,每一个线程都实行了统一个condition对象的await()要领,则挪用getWaitQueueLength(Condition condition)要领时返回的int值是5。

 

(4)、boolean hasQueuedThread(Thread thread)

  hasQueuedThread(Thread thread)的作用是查询指定的线程是不是正在守候猎取此锁定

  hasQueuedThreads()的作用是查询是不是有线程正在守候猎取此锁定。

 

(5)、boolean hasWaiters(Condition condition)

  hasWaiters(Condition condition)的作用是查询是不是有线程正在守候与此锁定有关的condition前提。

 

(6)、boolean isFair()

  isFair()的作用是推断是不是是平正锁

 

(7)、boolean isHeldByCurrentThread()

  isHeldByCurrentThread的作用是查询当前线程是不是坚持此锁定

 

(8)、boolean isLocked()

  isLocked()的作用是查询此锁定是不是由恣意的线程坚持

 

ReentrantReadWriteLock

类ReentrantLock具有完整互斥排他的效果,即统一时候只要一个线程在实行ReentrantLock.lock()要领背面的使命。如许做虽然保证了实例变量的线程平安性,但效力倒黑白常低下的。所以在JDK中供应了一种读写锁ReentrantReadWriteLock类,运用它能够加速运转效力,在某些不须要操纵实例变量的要领中,完整能够运用读写锁ReentrantReadWriteLock 来提拔该要领的代码运转速率。

读写锁示意也有两个锁,一个是读操纵相干的锁,也称为同享锁;另一个是写操纵相干的锁,也叫排他锁。也就是多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。在没有线程Thread举行写入操纵时,举行读取操纵的多个Thread都能够猎取读锁,而举行写入操纵的Thread只要在猎取写锁后才举行写入操纵。即多个Thread能够同时举行读取操纵,然则统一时候只许可一个Thread举行写入操纵。

 

一、ReentrantReadWriteLock读读同享

import java.util.concurrent.locks.ReentrantReadWriteLock;

class Service{
	private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
	
	public void read() {
		try {
			try {
				lock.readLock().lock();
				System.out.println("猎取读锁"+Thread.currentThread().getName()+" "+System.currentTimeMillis());
				Thread.sleep(10000);
			}finally {
				lock.readLock().unlock();
			}
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}


class MyThreadA extends Thread{
	private Service service;
	
	public MyThreadA(Service service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		service.read();
	}
}

class MyThreadB extends Thread{
	private Service service;
	
	public MyThreadB(Service service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		service.read();
	}
}

public class LockTest {
	
	public static void main(String[] args) throws InterruptedException {
		Service service=new Service();
		MyThreadA a=new MyThreadA(service);
		a.setName("A");
		MyThreadB b=new MyThreadB(service);
		b.setName("B");
		a.start();
		b.start();
	}

}

  

运转效果:

猎取读锁A 1575611161158
猎取读锁B 1575611161158

  

从输出效果打印的时候来看,两个线程险些同时进入lock()要领背面的代码。申明在此运用了lock.readLock()读锁能够进步递次运转效力,许可多个线程同时实行lock()要领背面的代码。

 

二、ReentrantReadWriteLock写写互斥

import java.util.concurrent.locks.ReentrantReadWriteLock;

class Service{
	private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
	
	public void write() {
		try {
			try {
				lock.writeLock().lock();
				System.out.println("猎取写锁"+Thread.currentThread().getName()+" "+System.currentTimeMillis());
				Thread.sleep(10000);
			}finally {
				lock.writeLock().unlock();
			}
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}


class MyThreadA extends Thread{
	private Service service;
	
	public MyThreadA(Service service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		service.write();
	}
}

class MyThreadB extends Thread{
	private Service service;
	
	public MyThreadB(Service service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		service.write();
	}
}

public class LockTest {
	
	public static void main(String[] args) throws InterruptedException {
		Service service=new Service();
		MyThreadA a=new MyThreadA(service);
		a.setName("A");
		MyThreadB b=new MyThreadB(service);
		b.setName("B");
		a.start();
		b.start();
	}

}

  

运转效果:

猎取写锁B 1575611458260
猎取写锁A 1575611468273

  

效果显现写锁的效果是统一时候只许可一个线程实行lock()背面的代码

 

三、ReentrantReadWriteLock读写互斥

import java.util.concurrent.locks.ReentrantReadWriteLock;

class Service{
	private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
	
	public void read() {
		try {
			try {
				lock.readLock().lock();
				System.out.println("猎取读锁"+Thread.currentThread().getName()+" "+System.currentTimeMillis());
				Thread.sleep(10000);
			}finally {
				lock.readLock().unlock();
			}
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public void write() {
		try {
			try {
				lock.writeLock().lock();
				System.out.println("猎取写锁"+Thread.currentThread().getName()+" "+System.currentTimeMillis());
				Thread.sleep(10000);
			}finally {
				lock.writeLock().unlock();
			}
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}


class MyThreadA extends Thread{
	private Service service;
	
	public MyThreadA(Service service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		service.read();
	}
}

class MyThreadB extends Thread{
	private Service service;
	
	public MyThreadB(Service service) {
		this.service=service;
	}
	
	@Override
	public void run() {
		service.write();
	}
}

public class LockTest {
	
	public static void main(String[] args) throws InterruptedException {
		Service service=new Service();
		MyThreadA a=new MyThreadA(service);
		a.setName("A");
		MyThreadB b=new MyThreadB(service);
		b.setName("B");
		a.start();	
		b.start();
	}

}

  

运转效果:

猎取读锁A 1575611689661
猎取写锁B 1575611699665

  

从读写的时候上能够看出读写的操纵时互斥的

 

腾讯云双十一活动