读-写锁 ReadWriteLock & 线程八锁
读-写锁 ReadWriteLock:
①ReadWriteLock 维护了一对相关的锁,一个用于只读操作, 另一个用于写入操作。
只要没有 writer,读取锁可以由 多个 reader 线程同时保持。写入锁是独占的。。
②ReadWriteLock 读取操作通常不会改变共享资源,但执行 写入操作时,必须独占方式来获取锁。
对于读取操作占多数的数据结构。 ReadWriteLock 能提供比独占锁更高 的并发性。
而对于只读的数据结构,其中包含的不变性可以完全不需要考虑加锁操作
TestReadWriteLock
package com.aff.juc; 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() { rw.set((int) Math.random() * 101);// [0-100]随机整数, 100+1 为[1-00] } }, "一个线程写:").start(); for (int i = 0; i <= 100; i++) { new Thread(new Runnable() { @Override public void run() { rw.get(); } }).start(); } } } class ReadWriteLockDemo { private int number = 0; private ReadWriteLock lock = new ReentrantReadWriteLock(); // 读取 public void get() { lock.readLock().lock();// 上锁 try { System.out.println(Thread.currentThread().getName() + " : " + number); } finally { lock.readLock().unlock();// 释放锁 } } // 写 public void set(int number) { lock.writeLock().lock();// 上锁 try { System.out.println(Thread.currentThread().getName()); this.number = number; } finally { lock.writeLock().unlock();// 释放锁 } } }
线程八锁:
① 一个对象里面如果有多个synchronized方法,某一个时刻内,
只要一个线程去调用 其中的一个synchronized方法了,
其它的线程都只能等待,换句话说,某一个时刻 内,只能有唯一一个线程去访问这些synchronized方法
② 锁的是当前对象this,被锁定后,其它的线程都不能进入到当前对象的其它的 synchronized方法
③ 加个普通方法后发现和同步锁无关
④ 换成两个对象后,不是同一把锁了,情况立刻变化。
⑤ 都换成静态同步方法后,情况又变化
⑥ 所有的非静态同步方法用的都是同一把锁——实例对象本身,
也就是说如果一个实 例对象的非静态同步方法获取锁后,
该实 例对象的其他非静态同步方法必须等待获 取锁的方法释放锁后才能获取锁,
可是别的实例对象的非静态同步方法因为跟该实 例对象的非静态同步方法用的是不同的锁,
所以毋须等待该实例对象已获取锁的非 静态同步方法释放锁就可以获取他们自己的锁。
⑦ 所有的静态同步方法用的也是同一把锁——类对象本身,这两把锁是两个不同的对 象,
所以静态同步方法与非静态同步方法之间是不会有竞态条件的。但是一旦一个 静态同步方法获取锁后,
其他静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法
之间还是不同的实例对象的静态同 步方法之间,只要它们同一个类的实例对象!
关键点:①非静态方法的默认锁为 this,静态方法的默认锁为对应的 Class 实例
②某一时刻内,只能有一个线程持有锁,无论几个方法。