多线程学习 读写锁

  类ReentranLock具有万川互斥排他的效果,即同一时间只有一个线程在执行ReentrantLock.lock()方法后面的任务。这样虽然保证了实例变量的线程安全性,

但效率却是非常低下的。所以在jdk中提供了一种读写锁ReentrantReadWriteLock类,使它可以加快运行效率,在某些不需要操作实例变量的方法中,完全可以使用读写锁

ReentrantReadWriteLock来提升该方法的代码运行速度。

  读写锁表示也有两个锁,一个是读操作相关的锁,也称为共享锁;另一个事写操作相关的做,也叫排他锁。也就是多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。

在没有现成Thread进行写入操作时,进行读取操作的多个Thread都可以获取读锁,而进行写入操作的Thread只有在获取写锁后才能进行写入操作。即多个Thread可以同时进行读取操作,但是同一时刻,只允许一个Thread进行写入操作。

  读读共享:

  Service类:

  

package ReadAndWriteLock;

import java.io.BufferedWriter;
import java.time.LocalDate;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public 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();
		}
	}
}

  主方法:

package ReadAndWriteLock;

public class Run {

		public static void main(String[] args) {
			final Service service=new Service();

			new Thread(new Runnable() {
				public void run() {
					service.read();
				}
			}).start();

			new Thread(new Runnable() {
				public void run() {
					service.read();
				}
			}).start();
		}

}

  控制台:

线程 : Thread-0  时间: 1534585340658  获得锁
线程 : Thread-1  时间: 1534585340659  获得锁

  可以发现,两个线程几乎同时进入了lock方法后面的代码,说明在此使用读写锁可以提供程序运行效率,允许多个线程同时制定lock()方法后面的代码。

  写写互斥:

  Service类

public class Service1 {

	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();
		}
	}

}

  主线程:

public class Run {

		public static void main(String[] args) {
			final Service1 service1=new Service1();

			new Thread(new Runnable() {
				public void run() {
					service1.write();
				}
			}).start();

			new Thread(new Runnable() {
				public void run() {
					service1.write();
				}
			}).start();
		}

}

  控制台:

线程:  Thread-0 时间:  1534585587952  获得锁
线程:  Thread-1 时间:  1534585597955  获得锁

  使用写锁代码lock.writeLock()的效果就是同意时间只允许一个线程执行lock()方法后面的代码。

  写读互斥:

  service2类

public class Service2 {

	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();
		}
	}
}

  主线程:

public class Run {

		public static void main(String[] args) {
			final Service2 service2=new Service2();

			new Thread(new Runnable() {
				public void run() {
					service2.write();
				}
			}).start();

			new Thread(new Runnable() {
				public void run() {
					service2.read();
				}
			}).start();
		}

}

  控制台:

线程: Thread-0  时间: 1534586198910
线程: Thread-1  时间: 1534586208910

  从时间上看,写读操作是互斥的。

  读写互斥:

  将主线程中的方法改为如下:

public class Run {

		public static void main(String[] args) throws InterruptedException {
			final Service2 service2=new Service2();

			new Thread(new Runnable() {
				public void run() {
					service2.read();
				}
			}).start();
			Thread.sleep(1000);
			new Thread(new Runnable() {
				public void run() {
					service2.write();
				}
			}).start();
		}

}

  控制台:

线程: Thread-0  时间: 1534586426809
线程: Thread-1  时间: 1534586436810

  读写操作也是互斥的。

  结论: 读写,写读,写写都是互斥的:而读读是异步的,非互斥的。

  每一个优秀的人,都有一段沉默的时光。不抱怨,不诉苦,最后度过那段感动自己的日子。

  

原文地址:https://www.cnblogs.com/hrlizhi/p/9498056.html

时间: 2024-10-21 06:31:18

多线程学习 读写锁的相关文章

skynet源码学习 - 读写锁

skynet 利用内置的原子操作来实现的一个读写锁,重点是理解 "full  memory barrier" ,UNPv2 中利用互斥和条件变量实现的读写锁.前者是在硬件支持的情况下,显得简单明了,站的层次不一样. 源码贴出来: struct rwlock { int write; int read; }; static inline void rwlock_init(struct rwlock *lock) { lock->write = 0; lock->read =

java多线程 -- ReadWriteLock 读写锁

写一条线程,读多条线程能够提升效率. 写写/读写 需要"互斥";读读 不需要互斥. ReadWriteLock 维护了一对相关的锁,一个用于只读操作,另一个用于写入操作.只要没有 writer,读取锁可以由多个 reader 线程同时保持.写入锁是独占的. ReadWriteLock 读取操作通常不会改变共享资源,但执行写入操作时,必须独占方式来获取锁.对于读取操作占多数的数据结构. ReadWriteLock 能提供比独占锁更高的并发性.而对于只读的数据结构,其中包含的不变性可以完全

C# 防止同时调用=========使用读写锁三行代码简单解决多线程并发的问题

http://www.jb51.net/article/99718.htm 本文主要介绍了C#使用读写锁三行代码简单解决多线程并发写入文件时提示"文件正在由另一进程使用,因此该进程无法访问此文件"的问题.需要的朋友可以参考借鉴 在开发程序的过程中,难免少不了写入错误日志这个关键功能.实现这个功能,可以选择使用第三方日志插件,也可以选择使用数据库,还可以自己写个简单的方法把错误信息记录到日志文件. 选择最后一种方法实现的时候,若对文件操作与线程同步不熟悉,问题就有可能出现了,因为同一个文

C#使用读写锁三句代码简单解决多线程并发写入文件时提示“文件正在由另一进程使用,因此该进程无法访问此文件”的问题

在开发程序的过程中,难免少不了写入错误日志这个关键功能.实现这个功能,可以选择使用第三方日志插件,也可以选择使用数据库,还可以自己写个简单的方法把错误信息记录到日志文件. 选择最后一种方法实现的时候,若对文件操作与线程同步不熟悉,问题就有可能出现了,因为同一个文件并不允许多个线程同时写入,否则会提示“文件正在由另一进程使用,因此该进程无法访问此文件”. 这是文件的并发写入问题,就需要用到线程同步.而微软也给进程同步提供了一些相关的类可以达到这样的目的,本文使用到的 System.Threadin

C#使用读写锁解决多线程并发写入文件时线程同步的问题

读写锁是以 ReaderWriterLockSlim 对象作为锁管理资源的,不同的 ReaderWriterLockSlim 对象中锁定同一个文件也会被视为不同的锁进行管理,这种差异可能会再次导致文件的并发写入问题,所以 ReaderWriterLockSlim 应尽量定义为只读的静态对象. 多线程同时写入文件 class Program { static int writeCount = 0; static int wrongCount = 0; static void Main(string

c++ 读写锁

#ifndef THREAD_UTIL_H #define THREAD_UTIL_H #include <pthread.h> namespace spider { class AutoLock { pthread_mutex_t * _lock; public: AutoLock(pthread_mutex_t * lock) { _lock = lock; pthread_mutex_lock(_lock); } ~AutoLock() { pthread_mutex_unlock(_l

Linux程序设计学习笔记----多线程编程线程同步机制之互斥量(锁)与读写锁

互斥锁通信机制 基本原理 互斥锁以排他方式防止共享数据被并发访问,互斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个互斥锁逻辑上绑定之后,对该资源的访问操作如下: (1)在访问该资源之前需要首先申请互斥锁,如果锁处于开状态,则申请得到锁并立即上锁(关),防止其他进程访问资源,如果锁处于关,则默认阻塞等待. (2)只有锁定该互斥锁的进程才能释放该互斥锁. 互斥量类型声明为pthread_mutex_t数据类型,在<bits/pthreadtypes.h>中有具体的定义. 互斥量

“全栈2019”Java多线程第四十二章:获取线程与读写锁的保持数

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多线程第四十二章:获取线程与读写锁的保持数 下一章 "全栈2019"Java多线程第四十三章:查询是否有线程在等待读写锁 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复&quo

【C/C++多线程编程之九】pthread读写锁

多线程编程之读写锁 Pthread是 POSIX threads 的简称,是POSIX的线程标准.  pthread读写锁把对共享资源的访问者分为读者和写者,读者只对共享资源进行读访问,写者只对共享资源进行写操作.在互斥机制,读者和写者都需要独立独占互斥量以独占共享资源,在读写锁机制下,允许同时有多个读者读访问共享资源,只有写者才需要独占资源.相比互斥机制,读写机制由于允许多个读者同时读访问共享资源,进一步提高了多线程的并发度.                   1.读写锁机制: