SpinLock实现,摘自并发编程网

package com.juc.simple;

import java.util.concurrent.atomic.AtomicReference;

/**
* a implement of spinlock based on cas
*
*/
public class SpinLock {
private AtomicReference<Thread> sign = new AtomicReference<>();
/**
* 让当前线程不停地的在循环体内执
* 当循环的条件被其他线程改变时 才能进入临界区
*/
public void lock() {
Thread current = Thread.currentThread();
//自旋,如果sign为null才能设置为current or memcachedb: checkandset
while (!sign.compareAndSet(null, current)) {
}
} public void unlock() {
Thread current = Thread.currentThread();
sign.compareAndSet(current, null);
}
}

这里是通过 AtomicReference实现的,而AtomicReference是通过volatile与Unsafe的CAS实现

volatile保证可见性,所有的线程看到的都是最新(主内存?)的值,但是volatile的操作不具有原子性,这样像(a++)这种操作就不能保证安全了,实际是读--修改--写操作的过程

AtomicReference的CAS操作更新值具有原子性

先来一段AtomicReference与volatile的比较

package com.juc.simple;

import java.util.concurrent.atomic.AtomicReference;

public class VolatileVsAtomicReference {

	private static volatile Integer volatileVar = 0;
//初始值value为0
private static AtomicReference<Integer> atomicReference=new AtomicReference<Integer>(volatileVar); public static void main(String[] args) { try {
testAtomicReference();
testVolatile();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
public static void testAtomicReference() throws InterruptedException{
for (int i = 0; i < 1000; i++) {
new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i < 1000; i++)
while(true){
Integer temp=atomicReference.get();
if(atomicReference.compareAndSet(temp, temp+1)){
break;
}
}
}
}).start();
}
Thread.sleep(1000);
System.out.println("atomicReference "+atomicReference.get()); //1000000
} public static void testVolatile() throws InterruptedException{
for (int i = 0; i < 1000; i++) {
new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
volatileVar=volatileVar++;
}
}
}).start();
}
Thread.sleep(1000);
System.out.println("volatileVar "+volatileVar); //may 8545
} }

结果:试过好几次volatileVar值都是不一样的

atomicReference 1000000
volatileVar 8545

这里可以看出如果用了CAS的话AtomicReference是可以保证原子性的,但如果只是简单的get()和set()方法是不行的,其实就等同于volatile,因为这货本身就是volatile实现的

参考

Java volatile reference vs. AtomicReference

oracle官方链接地址

get has the memory effects of reading a volatile variable.
set has the memory effects of writing (assigning) a volatile variable.

Java 理论与实践: 正确使用 Volatile 变量

AtomicReference的原代码实现

package java.util.concurrent.atomic;
import sun.misc.Unsafe; /**
* An object reference that may be updated atomically. See the {@link
* java.util.concurrent.atomic} package specification for description
* of the properties of atomic variables.
* @since 1.5
* @author Doug Lea
* @param <V> The type of object referred to by this reference
*/
public class AtomicReference<V> implements java.io.Serializable {
private static final long serialVersionUID = -1848883965231344442L; private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset; static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicReference.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
//volatile 变量
private volatile V value; /**
* Creates a new AtomicReference with the given initial value.
*
* @param initialValue the initial value
*/
public AtomicReference(V initialValue) {
value = initialValue;
} /**
* Creates a new AtomicReference with null initial value.
*/
public AtomicReference() {
} /**
* Gets the current value.
*
* @return the current value
*/
public final V get() {
return value;
} /**
* Sets to the given value.
*
* @param newValue the new value
*/
//volatile变量赋值
public final void set(V newValue) {
value = newValue;
} /**
* Eventually sets to the given value.
*
* @param newValue the new value
* @since 1.6
*/
//设置为新的值
public final void lazySet(V newValue) {
unsafe.putOrderedObject(this, valueOffset, newValue);
} /**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
* @param expect the expected value
* @param update the new value
* @return true if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
//如果当前值与期望值一致,则设置为新的值
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
} /**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
* and does not provide ordering guarantees, so is only rarely an
* appropriate alternative to {@code compareAndSet}.
*
* @param expect the expected value
* @param update the new value
* @return true if successful.
*/
public final boolean weakCompareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
} /**
* Atomically sets to the given value and returns the old value.
*
* @param newValue the new value
* @return the previous value
*/
//以原子方式设置为新的值,并且返回旧值
public final V getAndSet(V newValue) {
while (true) {
V x = get();
if (compareAndSet(x, newValue))
return x;
}
} /**
* Returns the String representation of the current value.
* @return the String representation of the current value.
*/
public String toString() {
return String.valueOf(get());
} }

最新文章

  1. mysqldump的实现原理
  2. win7 64的系统安装。net4.0总是提示安装未成功
  3. 从一个简单例子来理解js引用类型指针的工作方式
  4. 程序员藏经阁 Linux兵书
  5. css 字体超出隐藏
  6. Spark on YARN两种运行模式介绍
  7. apache配置Options详解
  8. Jenkins学习记录
  9. 黑马程序员——C语言基础 scanf函数 基本运算 三目运算符
  10. 为Magento2新主题添加使用Grunt
  11. Some tips on using HashSet&lt;T&gt; and List&lt;T&gt;
  12. php邮件发送 phpmailer
  13. PHP中的cookie创建取回删除;
  14. python-操作缓存
  15. poi读写Excel文件
  16. C# DropDownList绑定文件夹
  17. 驾驶机动车在高速公路上倒车、逆行、穿越中央分隔带掉头的一次记6分。 答案:错误 2013《123号令-附件2》一、机动车驾驶人有下列违法行为之一,一次记12分[重新考《科目一》]:(七)驾驶机动车在高速公路上倒车、逆行、穿越中央分隔带掉头的; 可以参考:http://zhinan.jxedt.com/info/6375.htm
  18. Thinkphp入门 四 —布局、缓存、系统变量 (48)
  19. sass学习笔记 -- sass的四种编译方法
  20. java中方法的定义

热门文章

  1. php 路径的理解
  2. javascript (2)
  3. less入门
  4. C#调用百度地图 api
  5. 我的C语言进化史
  6. 怎样在Windows资源管理器中添加右键菜单以及修改右键菜单顺序
  7. window.top.location.href 和 window.location.href 的区别
  8. java中 IndexOf()、lastIndexOf()、substring()的用法
  9. 获取Unity3D虚拟摄像机的图像
  10. redis lua