Java并发编程(七):ReadWriteLock读写锁与线程八锁
ReadWriteLock读写锁与线程八锁
场景
什么情况下采用读写锁?
- 写写操作/读写操作 需要互斥
- 读读操作 不需要互斥
如果都用独占锁,有时候很多读操作并发时其实并不需要锁住缺上了锁,导致效率低下,可以采用读写锁来代替:
import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class TestReadWriteLock {
public static void main(String[] args)
{
ReadWriteLockDemo rw = new ReadWriteLockDemo();
new Thread(new Runnable() {
@Override
public void run() {
try {
//等一下,让一些读线程先读
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 写一个 随机数
rw.setNumber(new Random().nextInt(111));
}
},"Write:").start();
// 起100个线程去读
for(int i= 0;i<100;i++)
{
new Thread(new Runnable() {
@Override
public void run() {
rw.getNumber();
}
},"Read:") .start();
}
}
}
class ReadWriteLockDemo{
private int number = 0;
private ReadWriteLock lock = new ReentrantReadWriteLock();
//读
public void getNumber(){
lock.readLock().lock();
try{
System.out.println(Thread.currentThread().getName()+":"
+ number);
}
finally {
lock.readLock().unlock();
}
}
//写
public void setNumber(int number)
{
lock.writeLock().lock();
try
{
System.out.println(Thread.currentThread().getName());
this.number = number;
}
finally {
lock.writeLock().unlock();
}
}
}
代码逻辑:
- 一个线程去写,稍微延迟一会,先让几个线程读一下
- 100个线程去读
实际执行结果:
Read::0
Read::0
Read::0
Read::0
Write:
Read::23
Read::23
Read::23
Read::23
......//后面全是Read::23
刚开始写线程还没写,读线程先读了4个0,后面写锁抢占,写入了数据,释放锁
释放之后,其他读线程继续读,读到的都是23
解决的问题
用读写锁代替独占锁,提高了效率
线程八锁
看以下代码:
/** * 题目:判断打印的 "one" or "two" * * 1.两个普通同步方法,两个线程,标准打印 one two * 2.新增 Thread.sleep()方法给 getOne ,打印 one two * 3.新增 普通方法 getThree(),打印 three one two * 4.两个普通的同步方法,两个Number对象,打印 two one * 5.修改getOne为静态同步方法,打印 two one * 6.修改两个方法均为静态同步方法,一个Number对象,打印 one two * 7.一个静态同步方法,一个非静态同步方法,两个Number对象,打印 two one * 8.两个静态同步方法,两个Number对象,打印 one two * */
public class TestThread8Monitor {
public static void main(String[] args)
{
Number number = new Number();
Number number2 = new Number();
new Thread(() -> number.getOne()).start();
new Thread(()->number2.getTwo()).start();
// new Thread(()->number2.getTwo()).start();
// new Thread(()->number.getThree()).start();
}
}
class Number{
public static synchronized void getOne(){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("one");
}
public static synchronized void getTwo(){
System.out.println("two");
}
public synchronized void getThree(){
System.out.println("three");
}
}
代码逻辑和执行结构都写在上面了
发生了什么?
关键点
- 非静态方法的锁 默认为this,即锁住了当前的类对象
- 静态方法的锁 为对应的Class 实例,即锁住了对应类的对象
- 某一个时刻内,只能有一个线程持有锁,无论几个方法
由于两个number对象都是由Number的class类的实例对象产生的,所以如果锁住了class类的实例对象,其他任何number对象都无法获取锁;
如果锁住了this,即number锁住了number对象,number2锁住了number2对象,那么就互不影响了;
同理锁住this和锁住class类的实例对象也互不影响
还没有评论,来说两句吧...