Java专题十三(2):线程安全与同步
2021-02-07 17:15
标签:roc 顺序 线程安全 eva nal 消费者 静态方法 exception ring 假设我们要实现一个视频网站在线人数统计功能,在每个客户端登录网站时,统计在线人数,通常用一个变量count代表人数,用户上线后,count++ 假设目前在线人数count是10,甲登录网站,网站后台读取到count值为10(count++分为三步:读取-修改-写入),还没来得及修改,这时乙也在登录,后台读取到count值也为10,最终甲、乙登录完成后,count变为了11,正确结果本来应该是12的 java.util.concurrent.atomic包中有很多原子变量,用于对数据进行原子操作 位于 可重入锁:同一线程在方法获取锁的时候,在进入前面方法内部调用其它方法会自动获取锁 乐观锁:乐观地认为其他人读数据时都不会修改数据,不会上锁 假设现在有一个类使用信号量去实现资源池,生产者消费者模式线程同步 首先定义2个信号量 生产消费操作实现方法: 从池中取出资源( 放入资源至池中( Java专题十三(2):线程安全与同步 标签:roc 顺序 线程安全 eva nal 消费者 静态方法 exception ring 原文地址:https://www.cnblogs.com/myibu/p/12775684.htmlJava专题十三(2):线程安全与同步
多个线程访问共享资源和可变资源时,由于线程执行的随机性,可能导致程序出现错误的结果
class Online{
int count;
public Online(){
this.count = 0;
}
public void login(){
count++;
}
}
原子变量
如对于上面的问题,可以用AtomicInteger原子变量的incrementAndGet()来实现正确操作synchronized关键字
public synchronized void login(){
count++;
}
静态方法内代码:synchronized(Online.class)
非静态方法内代码:synchronized(this)
public void login(){
synchronized(this){
count++;
}
}
锁机制
java.util.concurrent.locks
包中public interface Lock {
void lock();
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}
锁
说明
ReentrantLock
可重入互斥锁
ReentrantReadWriteLock
可重入读写锁
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}}
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();
}
}
}}
一些锁的概念
公平锁:按照线程锁申请后顺序来获取锁
非公平锁:不一定按照线程锁申请先后顺序来获取锁
悲观锁:悲观地认为其他人读数据时都会修改数据,会上锁,别人只能等待它释放锁
共享锁:同一时刻可以被多个线程拥有
独占锁:同一时刻只能被一个线程拥有计数信号量
java.util.concurrent.Semaphore
通常一个信号量维持着一个许可证的集合,acquire
方法会申请许可证permit
,让线程阻塞直到许可证是空的,而release
方法会释放一个许可证
public class Pool
Semaphore
:
availableItems
代表可用资源数,数值初始化为0
availableSpaces
可用空间数,数值初始化为capacity
take
):
availableItems.acquire()
查询availableItems
许可证,该方法会阻塞直到池中有可用资源doExtract方法
)availableSpaces.release()
释放许可证,表示池中多了一个可用的空间,可以用来存放新的资源put
):
availableSpaces.acquire()
查询availableSpaces
许可证,该方法会阻塞直到池中有可用空间doInsert方法
)availableItems.release()
释放许可证,表示池中多了一个可用资源,可以来访问该资源
文章标题:Java专题十三(2):线程安全与同步
文章链接:http://soscw.com/index.php/essay/52268.html