Lock接口与读写锁(lock 和 synchronized 的比较)
2017-08-10 15:31
519 查看
出现:JDK1.5实现类:ReentrantLock(重入锁、手工锁)ReentrantReadWriteLock.ReadLock ReentrantReadWriteLock.WriteLock主要方法:lock() unlock()使用:TestLock.java1
public class TestLock implement Runnable{23
ReentrantLock lock = new ReentrantLock();45
@Override6
public void run(){78
try{9
//加锁10
lock.lock();11
//执行同步代码12
}13
finally{14
//释放锁15
lock.unlock();16
}1718
}和synchronized互斥锁的比较:(1)synchronized关键字修饰的代码是完全互斥的,而Lock更加灵活,可以实现多线程同时读共享数据(读锁和读锁不互斥),但读锁和写锁互斥。写锁和写锁互斥(读写锁)。(2)ReentrainLock有tryLock方法:1
public class ReentrainLockTest{2
//获取锁3
Lock lock = new ReentrainLock();4
//线程1的方法:获取锁5
void m1(){6
lock.lock();//锁定7
try{8
for(int i=0;i<10;i++){//锁定10秒9
TimeUtil.SECONDS.sleep(1);//sleep 1秒10
}11
}catch(InterruptException e){12
e.printStackTrace();13
}finally{14
lock.unlock();//10秒后释放锁15
}16
}17
//线程2的方法18
void m2(){19
boolean locked = lock.tryLcok();//尝试锁定,如果返回为false,则获取锁失败,但程序继续执行。20
Systerm.out.println("是否获得锁:" + locked);21
if(locked) lock.unlock();//如果获得锁,则解锁22
}2324
public static void main(String[] args){25
//开启两个线程,线程1调用m1方法,线程2调用m2方法26
}27
}(3)lockInterruptibly方法持有的锁,如果没获取到锁可被其它线程打断1
public class{2
public static void main(Stirng[] args){3
Lock lock = new ReentrainLock();4
//1.创建t1线程,一直持有锁5
Thread t1 = new Thread(()-> {6
lock.lock();7
try{8
while(true){//一直持有锁9
TimeUtils.SECOND.sleep(1);10
}11
}catch(InterruptException e){12
e.printStackTrace();13
}fainally{14
lock.unlock();//释放锁15
}16
});17
t1.start();1819
//2.启动t2线程,尝试获取锁,但是一直获取失败(t1线程一直持有锁)20
Tread t2 = new Thread(()->{21
try{22
boolean isLocked = lock.tryLock();23
lock.lockInterruptibly();//表示可以对其它线程的interrupt方法做出响应24
System.out.println("t2线程启动!");25
}catch(InterruptException e){26
e.printStackTrace();27
}finally{28
if(isLocked) lock.unlock();29
}3031
});32
t2.start();3334
//3.主线程1秒后打断t2线程的等待锁状态,t2线程结束,抛出异常35
try{36
timeUtils.SECONDS.sleep(1)37
}catch(InterruptException e){38
e.printStackTrace();39
}40
t2.interrupt();41
}42
}(4)reentrianLock可以指定公平锁(synchronized为不公平锁)synchronized在锁释放时,所有线程都在竞争锁(不确定谁能拿到锁),很可能有的线程一次都拿不到,不公平reentrianLock可以在锁竞争时,判断哪个线程等待的时间长,就先让哪个线程获取锁1
Lock lock = new ReentrainLock(true);//传入true为公平锁,默认为非公平锁读写锁接口:ReadWriteLock实现类:ReentranReadWriteLock方法:readLock、writeLock(返回Lock对象)使用:1
ReadWriteLock rwl = new ReenTranReadWriteLock();2
rwl.readLock().lock();//获取读锁3
rwl.readLock().unLock();//释放读锁45
rwl.writeLock().lock();//获取写锁6
rwl.writeLock().unLock();//释放写锁例子:用户从银行读取余额(读锁,多用户同时读一个账号)。用户从银行存取钱(写锁,每次只能一个用户从同一个账号存取钱)用户账户类:MyAccount.java1
public class MyCount {2
private String oid; //账号3
private int cash; //账户余额45
MyCount(String oid, int cash) {6
this.oid = oid;7
this.cash = cash;8
}910
public String getOid() {11
return oid;12
}1314
public void setOid(String oid) {15
this.oid = oid;16
}1718
public int getCash() {19
return cash;20
}2122
public void setCash(int cash) {23
this.cash = cash;24
}2526
@Override27
public String toString() {28
return "MyCount{" +29
"oid='" + oid + '\'' +30
", cash=" + cash +31
'}';32
}33
}线程类(多用户同时访问一个账号):UserThread.java1
public class UserThread implements Runnable {2
private String name; //用户名3
private MyCount myCount; //所要操作的账户4
private int iocash; //操作的金额,当然有正负之分了5
private ReadWriteLock myLock; //执行操作所需的锁对象6
private boolean ischeck; //是否查询78
public UserThread(String name, MyCount myCount, int iocash, ReadWriteLock myLock, boolean ischeck) {9
this.name = name;10
this.myCount = myCount;11
this.iocash = iocash;12
this.myLock = myLock;13
this.ischeck = ischeck;//是否查看余额14
}1516
public void run() {17
if (ischeck) {//查看余额18
//获取读锁19
myLock.readLock().lock();20
System.out.println("读:" + name + "正在查询" + myCount + "账户,当前金额为" + myCount.getCash());21
//释放读锁22
myLock.readLock().unlock();23
} else {//存取钱24
//获取写锁25
myLock.writeLock().lock();26
//执行现金业务27
System.out.println("写:" + name + "正在操作" + myCount + "账户,金额为" + iocash +",当前金额为" + myCount.getCash());28
myCount.setCash(myCount.getCash() + iocash);29
System.out.println("写:" + name + "操作" + myCount + "账户成功,金额为" + iocash +",当前金额为" + myCount.getCash());30
//释放写锁31
myLock.writeLock().unlock();32
}33
}34
}测试类:Test.java1
public class Test {2
public static void main(String[] args) {3
//创建并发访问的账户4
MyCount myCount = new MyCount("95599200901215522", 10000);5
//创建一个锁对象6
ReadWriteLock lock = new ReentrantReadWriteLock(false);7
//创建一个线程池8
ExecutorService pool = Executors.newFixedThreadPool(2);9
//创建一些并发访问用户,一个信用卡,存的存,取的取,好热闹啊10
User u1 = new User("Mike", myCount, -4000, lock, false);11
User u2 = new User("Mike's Dad", myCount, 6000, lock, false);12
User u3 = new User("Mike's Brother", myCount, -8000, lock, false);13
User u4 = new User("Mike's Mom", myCount, 800, lock, false);14
User u5 = new User("Mike's son", myCount, 0, lock, true);15
//在线程池中执行各个用户的操作16
pool.execute(u1);17
pool.execute(u2);18
pool.execute(u3);19
pool.execute(u4);20
pool.execute(u5);21
//关闭线程池22
pool.shutdown();23
}24
}锁升级和降级原则:读锁不可升级成写锁(读锁释放前不可以加写锁)写锁可以降级成读锁(写锁释放前可以加读锁)官方文档读写锁例子:1
class CachedData {2
Object data;3
volatile boolean cacheValid;4
final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();56
void processCachedData() {7
rwl.readLock().lock();8
if (!cacheValid) {//第一重检测,没有缓存数据,释放读锁,加写锁写数据9
// 在写锁前必须释放读锁10
rwl.readLock().unlock();11
rwl.writeLock().lock();12
try {13
//第二重检测,写数据前再次确保缓存没有数据,防止在第10行释放了读锁后,被其它线程的写锁拿到,往缓存里写了数据14
if (!cacheValid) {15
data = ...//数据库写入修改操作16
cacheValid = true;17
}18
// 锁降级,在写锁里面先上读锁,把写锁降级成读锁19
rwl.readLock().lock();20
} finally {21
rwl.writeLock().unlock(); // 在读锁状态下释放写锁22
}23
}2425
try {26
use(data);27
} finally {28
rwl.readLock().unlock();29
}30
}31
}
相关文章推荐
- Java并发18:Lock系列-Lock接口与synchronized关键字的比较
- 比较ReentrantLock和synchronized和信号量Semaphore实现的同步性能
- synchronized关键字、ReentrantLock与原子类比较
- java多线程:synchronized和lock比较浅析
- (转)Lock和synchronized比较详解
- synchonized比较Lock接口
- Lock和synchronized比较详解
- Lock接口与Synchronized关键字的区别
- Lock和synchronized比较详解(转)
- 一道面试题比较synchronized和读写锁
- 【Java基础之线程同步(二)】java线程同步:synchronized关键字,Lock接口以及可重入锁ReentrantLock
- (转)Lock和synchronized比较详解
- Lock和Synchronized的比较
- Lock和synchronized比较详解
- Lock和Synchronized的比较
- (转载)StampedLock、ReadWriteLock以及synchronized的比较
- Lock与synchronized 的比较学习
- synchronized与ReentrantLock的介绍、使用、适合场景及比较
- Lock和synchronized比较详解
- Lock和synchronized比较详解