【java并发】基于JUC CAS原理,自己实现简单独占锁
2013-08-19 00:21
871 查看
synchronized的基本原理回顾
在jvm内部,所有对象都含有单一的锁,jvm负责跟踪监视被加锁次数,叫做对象监视器。当线程第一次给对象加锁的时候,计数器会加1,离开时会减1.同样任务是可重入的,每次重入也是加1,离开减1.synchronized是独占式的,拿到对象锁才能继续,没有获取到锁就会阻塞。
JUC CAS乐观锁基本原理
synchronized就是一种独占锁,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。乐观锁就是假设没有冲突而去完成某项操作,如果因为冲突失败就重试。
原理有点类似于在数据库记录字段增加一个版本号,每次更新的时候做两个事情:
1.检查数据库记录当前的版本号和读取到的版本号是否一致,不一致说明数据已不是最新,更新失败需要重试.
2.如果版本号一致,更新成功,同时将版本号加1.
在jdk1.5开始,Doug Lea在JUC类库里提供了类似的乐观锁的机制叫CAS.
CAS简介:compareAndSet的意思,就是先比较是否是期望值(是期望值,说明没人更改过,当然也有可能有ABA情况),如果是再设值,不是就设值失败,线程阻塞。如果是基于这个,就要保证比较和设值这两个动作是原子性的,如何保证呢?这个是借助于JNI,利用CPU硬件支持来完成的。利用硬件提供swap和test_and_set指令,单CPU下同一指令的多个指令周期不可中断,SMP中通过锁总线支持这两个指令的原子性。
volilate关键字
Java语言规范允许线程保存共享成员变量的私有拷贝,当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。这样就延伸出可见性的一个问题。
CAS解决了比较和更新的原子性,但是还有另外一个问题就是要保证可见性。Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
volatile关键字有两层含义:
1.对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。
2.volatile前后的代码不能重排
其他话题
volilate和cas只能乐观锁保证的状态控制的正确,而在设置状态失败的时候,仍然需要阻塞线程。juc里提供了LockSupport的park和unpark方法用于阻塞线程。而不同的场景下需要不同的等待策略和锁共享策略,juc提供了AbstractQueuedSynchronizer(AQS)为基类的一序列不同的锁,底层都是基于CAS、LocakSupport和Queue来管理,后续有时间细细分析。
juc基于的CAS,提供了带有原子性的基本类型封装类,如AtomicInteger、AtomicLong等。
AtomicInteger原理:
如自增:
Java代码
/**
* Atomically increments by one the current value.
*
* @return the previous value
*/
public final int getAndIncrement() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next)) //cas
return current;
}
}
/** * Atomically increments by one the current value. * * @return the previous value */ public final int getAndIncrement() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) //cas return current; } }
compareAndSet的实现如下:
Java代码
public final boolean compareAndSet(int expect, int update) {
urn unsafe.compareAndSwapInt(this, valueOffset, expect, update); //JNI调用
}
public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); //JNI调用 }
自己实现简单乐观独占锁
基于cas,本人简单实现了一个乐观独占锁,代码如下:基于CAS简单乐观独占锁
Java代码
package lock.test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;
/**
* 简单乐观独占锁
*/
public class OptimisticExclusiveLock {
/**
* 独占锁标记 true 锁不可用 false 锁可用
*/
private AtomicBoolean state = new AtomicBoolean(false);
List<Thread> queue = new ArrayList<Thread>();//阻塞队列
public boolean lock() {
if (!state.get()&&state.compareAndSet(false, true)) {//取锁成功不会阻塞,程序会继续执行
return true; // 利用CAS
} else {
queue.add(Thread.currentThread());//加入阻塞队列
LockSupport.park();//阻塞线程
return false;
}
}
public boolean unLock() {
if (state.get()) {
queue.remove(Thread.currentThread());//从队列里移除
if (state.compareAndSet(true, false)) {// 利用CAS
if(!queue.isEmpty()){
LockSupport.unpark(queue.get(0));//唤醒第一个等待线程
}
return true;
}
return false;
} else {
return false;
}
}
}
package lock.test; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.LockSupport; /** * 简单乐观独占锁 */ public class OptimisticExclusiveLock { /** * 独占锁标记 true 锁不可用 false 锁可用 */ private AtomicBoolean state = new AtomicBoolean(false); List<Thread> queue = new ArrayList<Thread>();//阻塞队列 public boolean lock() { if (!state.get()&&state.compareAndSet(false, true)) {//取锁成功不会阻塞,程序会继续执行 return true; // 利用CAS } else { queue.add(Thread.currentThread());//加入阻塞队列 LockSupport.park();//阻塞线程 return false; } } public boolean unLock() { if (state.get()) { queue.remove(Thread.currentThread());//从队列里移除 if (state.compareAndSet(true, false)) {// 利用CAS if(!queue.isEmpty()){ LockSupport.unpark(queue.get(0));//唤醒第一个等待线程 } return true; } return false; } else { return false; } } }
简单乐观独占锁测试
Java代码
package lock.test;
/**
* @author Administrator 独占锁测试
*/
public class OptimisticExclusiveLockTest {
public static OptimisticExclusiveLock lock = new OptimisticExclusiveLock(); // 独占锁
public static volatile int i = 0; // 保证可见性
public class Task implements Runnable {
@Override
public void run() {
while (true) {
try {
lock.lock();//加锁
i += 2;
System.out.println("thread name:" + Thread.currentThread().getName() + " i=" + i);
} finally {
lock.unLock();//释放锁
try {
Thread.currentThread().sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public void runTask() {
for (int i = 0; i < 100; i++) {
Thread t = new Thread(new Task(), "thread" + i);
t.start();
}
}
public static void main(String[] args) {
OptimisticExclusiveLockTest test = new OptimisticExclusiveLockTest();
test.runTask();
}
}
package lock.test; /** * @author Administrator 独占锁测试 */ public class OptimisticExclusiveLockTest { public static OptimisticExclusiveLock lock = new OptimisticExclusiveLock(); // 独占锁 public static volatile int i = 0; // 保证可见性 public class Task implements Runnable { @Override public void run() { while (true) { try { lock.lock();//加锁 i += 2; System.out.println("thread name:" + Thread.currentThread().getName() + " i=" + i); } finally { lock.unLock();//释放锁 try { Thread.currentThread().sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } public void runTask() { for (int i = 0; i < 100; i++) { Thread t = new Thread(new Task(), "thread" + i); t.start(); } } public static void main(String[] args) { OptimisticExclusiveLockTest test = new OptimisticExclusiveLockTest(); test.runTask(); } }
这里实现的简单乐观独占锁很简单,但是能保证并发性。
JUC里面基于CAS实现了很多的锁,主要是基于AQS实现,如ReentrantLock,CountDownLatch,Semaphore,FutureTask等,适用于不同的锁场景。
转自:/article/4132757.html
相关文章推荐
- Java并发之CAS与原子类实现原理讲解
- 深入剖析基于并发AQS的(独占锁)重入锁(ReetrantLock)及其Condition实现原理
- 深入剖析基于并发AQS的(独占锁)重入锁(ReetrantLock)及其Condition实现原理
- Java并发编程札记-(六)JUC线程池-02ThreadPoolExecutor实现原理
- java——HashMap的实现原理,自己实现简单的HashMap
- 基于JVM原理、JMM模型和CPU缓存模型深入理解Java并发编程
- Java并发包中的同步队列SynchronousQueue实现原理
- 基于Java关于链表的简单实现
- java并发编程之:ReentrantLock实现原理与深入研究
- Java并发 利用多写Redis实现分布式锁原理
- 【死磕Java并发】—–深入分析synchronized的实现原理
- Dubbo原理简介------自己动手实现简单的RPC调用
- java并发前身CAS原理深度分析
- IOS 基于APNS消息推送原理与实现(JAVA后台)
- iOS 基于APNS消息推送原理与实现(包括JAVA后台代码)
- Java 并发集合的实现原理
- java并发机制的底层实现原理
- 深入理解Java并发之synchronized实现原理
- Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS
- IOS 基于APNS消息推送原理与实现(JAVA后台)