线程安全4 - Lock锁
2019-09-29 本文已影响0人
小超_8b2f
0. Lock就是来替换synchronized的
public class TestSynchronized {
public static void main(String[] args) {
TestSynchronized obj = new TestSynchronized();
obj.init();
}
private void init() {
OutPut out = new OutPut();
new Thread() {
@Override
public void run() {
while(true)
out.print("hello world");
};
}.start();
new Thread() {
@Override
public void run() {
while(true)
out.print("guchunchaoxixihaha");
};
}.start();
}
class OutPut {
public synchronized void print(String str) {
for(int i = 0; i < str.length(); i++) {
System.out.print(str.charAt(i));
}
System.out.println();
}
}
}
用Lock替代写法:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
public static void main(String[] args) {
TestLock obj = new TestLock();
obj.init();
}
private void init() {
OutPut out = new OutPut();
new Thread() {
@Override
public void run() {
while(true)
out.print("hello world");
};
}.start();
new Thread() {
@Override
public void run() {
while(true)
out.print("guchunchaoxixihaha");
};
}.start();
}
class OutPut {
Lock lock = new ReentrantLock();
public void print(String str) {
lock.lock();
try {
for(int i = 0; i < str.length(); i++) {
System.out.print(str.charAt(i));
}
System.out.println();
} finally {
lock.unlock();
}
}
}
}
1. 读写锁:ReentrantReadWriteLock
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLogTest {
public static void main(String[] args) {
final Queue3 queue = new Queue3();
for(int i = 0; i < 3; i++) {
new Thread(new Runnable() { //读线程
public void run() {
while(true) {
queue.get();
}
}
}).start();
new Thread(new Runnable() { //写线程
public void run() {
while(true) {
queue.write((int)(Math.random() * 1000));
}
}
}).start();
}
}
}
class Queue3 {
//共享数据,只能有一个线程能写该数据,但可以有多个线程同时读取该数据
private Object data = null;
ReadWriteLock rwl = new ReentrantReadWriteLock();
//读数据上读锁,多个读进程可同时进行,但不能喝写进程同时进行
public void get() {
rwl.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " be ready to read data.");
Thread.sleep((long)Math.random()*1000);
System.out.println(Thread.currentThread().getName() + " have read data:" + data);
System.out.println();
} catch (Exception e) {
e.printStackTrace();
} finally {
rwl.readLock().unlock();
}
}
public void write(Object data) { //写数据上写锁,排他
rwl.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " be ready to write data.");
Thread.sleep((long)Math.random()*1000);
this.data = data;
System.out.println(Thread.currentThread().getName() + " have write data:" + data);
System.out.println();
} catch (Exception e) {
e.printStackTrace();
} finally {
rwl.writeLock().unlock();
}
}
}
2. Hibernate load()和get区别,用缓存实现代理类
User user = session.load(id,User.class); //无值则一个返回代理对象:User$Proxy
User user = session.get(id,User.class); //无值则返回null
User$Proxy extends User {
private Integer id = id;
User realUser = null;
String getName() {
if(realUser == null) {
realUser = session.get(id);
if(realUser == null) throw exception......
return realUser.getName();
}
}
}
3. JAVA API ReentrantReadWriteLock 示例程序:读写锁共存
class CachedData {
Object data;
volatile boolean cacheValid;
final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
void processCachedData() {
rwl.readLock().lock();
if (!cacheValid) { //未被缓存过,初次赋值。上写锁,只能有一个线程写
// Must release read lock before acquiring write lock
rwl.readLock().unlock();
rwl.writeLock().lock();
try {
// Recheck state because another thread might have
// acquired write lock and changed state before we did.
if (!cacheValid) {
data = ...
cacheValid = true;
}
// Downgrade by acquiring read lock before releasing write lock
rwl.readLock().lock();
} finally {
rwl.writeLock().unlock(); // Unlock write, still hold read
}
}
try {
use(data); //读锁可以让多个线程同时读
} finally {
rwl.readLock().unlock();
}
}
}