0
点赞
收藏
分享

微信扫一扫

并发编程-Volatile的伪共享和重排序

上一篇 <<<Volatile解决JMM的可见性问题
下一篇 >>>CAS无锁模式及ABA问题


Volatile的伪共享问题

Volatile的伪共享解决办法

/**
* 解决办法:【数据填充】
* JDK6中,定义p1-6,加上value,一共占用56个字节 ,在加上VolatileLong类中头占用8个字节一共就是占用64个字节。
* public final static class VolatileLong{
* public volatile long value = 0L;
* public long p1, p2, p3, p4, p5, p6;
* }
* jdk7中,写个类单独继承方
* public final static class VolatileLong extends AbstractPaddingObject {
* public volatile long value = 0L;
* }
* public class AbstractPaddingObject {
* public long p1, p2, p3, p4, p5, p6;
* }
* jdk8中,使用注解@sun.misc.Contended,启动的时候需要加上该参数-XX:-RestrictContended
* ConcurrentHashMap中就使用了此注解
* @sun.misc.Contended static final class CounterCell {}
*
*/

public class FalseShareTest implements Runnable {
// 定义4和线程
public static int NUM_THREADS = 4;
// 递增+1
public final static long ITERATIONS = 500L * 1000L * 1000L;

private final int arrayIndex;
// 定义一个 VolatileLong数组
private static VolatileLong[] longs;
// 计算时间
public static long SUM_TIME = 0l;

public FalseShareTest(final int arrayIndex) {
this.arrayIndex = arrayIndex;
}

public static void main(final String[] args) throws Exception {
for (int j = 0; j < 10; j++) {
System.out.println(j);
if (args.length == 1) {
NUM_THREADS = Integer.parseInt(args[0]);
}
longs = new VolatileLong[NUM_THREADS];
for (int i = 0; i < longs.length; i++) {
longs[i] = new VolatileLong();
}
final long start = System.nanoTime();
runTest();
final long end = System.nanoTime();
SUM_TIME += end - start;
}
System.out.println("平均耗时:" + SUM_TIME / 10);
}

private static void runTest() throws InterruptedException {
Thread[] threads = new Thread[NUM_THREADS];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new FalseShareTest(i));
}
for (Thread t : threads) {
t.start();
}
for (Thread t : threads) {
t.join();
}
}

public void run() {
long i = ITERATIONS + 1;
while (0 != --i) {
longs[arrayIndex].value = i;
}
}
@sun.misc.Contended
public final static class VolatileLong {
// extends AbstractPaddingObject
// 8个字节 对象占用8个字节
public volatile long value = 0L;
// public long p1, p2, p3, p4, p5, p6;
// 48+ 64
}
}

Volatile解决重排序问题

/**
* thread1和thread2在单线程情况下重排序都没问题,但在多线程下就存在重排序的问题:
* 第856750次(0,1)
* 第856751次(0,1)
* 第856752次(0,0)
* 解决办法:使用volatile或手动插入屏障
* UnSafeUtils.getUnsafe().loadFence()--读屏障
* UnSafeUtils.getUnsafe().storeFence();--写屏障
*
*
**/

public class ReorderThread {
// 全局共享的变量
private /*volatile*/ static int a = 0, b = 0;
private /*volatile*/ static int x = 0, y = 0;


public static void main(String[] args) throws InterruptedException {
int i = 0;
while (true) {
i++;
a = 0;
b = 0;
x = 0;
y = 0;
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
a = 1;
//插入一个内存写屏障
UnSafeUtils.getUnsafe().storeFence();
x = b;

}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
b = 1;
//插入一个内存写屏障
UnSafeUtils.getUnsafe().storeFence();
y = a;
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("第" + i + "次(" + x + "," + y + ")");
if (x == 0 && y == 0) {
break;
}
}
}
}

双重检验锁的单例也应该加上volatile

/**
* 双重检验锁的单例也应该加上volatile
*
* new Singleton03()完成的动作:
* 1.分配对象的内存空间memory=allocate();
* 2.调用构造函数初始化
* 3.将对象复制给变量
*
* 第二步和第三步流程存在重排序,将对象复制给变量,在执行调用构造函数初始化,导致另外一个线程获取到该对象不为空,但是该改造函数没有初始化,所以就报错了
*
*/

public class Singleton03 {
private static volatile Singleton03 singleton03;

public static Singleton03 getInstance() {
// 第一次检查
if (singleton03 == null) {
//第二次检查
synchronized (Singleton03.class) {
if (singleton03 == null) {
singleton03 = new Singleton03();
}
}
}
return singleton03;
}

public static void main(String[] args) {
Singleton03 instance1 = Singleton03.getInstance();
Singleton03 instance2 = Singleton03.getInstance();
System.out.println(instance1==instance2);
}
}

Volatile和synchronized区别?


相关文章链接:
<<<多线程基础
<<<线程安全与解决方案
<<<锁的深入化
<<<锁的优化
<<<Java内存模型(JMM)
<<<Volatile解决JMM的可见性问题
<<<CAS无锁模式及ABA问题
<<<Synchronized锁
<<<Lock锁
<<<AQS同步器
<<<Condition
<<<CountDownLatch同步计数器
<<<Semaphore信号量
<<<CyclicBarrier屏障
<<<线程池
<<<并发队列
<<<Callable与Future模式
<<<Fork/Join框架
<<<Threadlocal
<<<Disruptor框架
<<<如何优化多线程总结

举报

相关推荐

0 条评论