栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

多线程与高并发学习二

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

多线程与高并发学习二

多线程与高并发学习二
    • Volatile不能保证原子性
    • 锁的细化DEMO
      • 应该避免锁定对象的引用变成另外的对象
      • CAS的ABA问题理解

Volatile不能保证原子性
public class VolatileNotSync {
    volatile int count = 0;

    void m() {
        for (int i = 0; i < 10000; i++) count++;
    }

    public static void main(String[] args) {
        T04_VolatileNotSync t = new T04_VolatileNotSync();

        List threads = new ArrayList();

        for (int i = 0; i < 10; i++) {
            threads.add(new Thread(t::m, "thread-" + i));
        }

        threads.forEach((o) -> o.start());

        threads.forEach((o) -> {
            try {
                o.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        System.out.println(t.count);


    }

}

输出结果如下(如果能保证原子性的话则应输出100000):

锁的细化DEMO
public class FineCoarseLock {

    int count = 0;

    synchronized void m1() {
        //do sth need not sync
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //业务逻辑中只有下面这句需要sync,这时不应该给整个方法上锁
        count++;

        //do sth need not sync
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    void m2() {
        //do sth need not sync
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //业务逻辑中只有下面这句需要sync,这时不应该给整个方法上锁
        //采用细粒度的锁,可以使线程争用时间变短,从而提高效率
        synchronized (this) {
            count++;
        }
        //do sth need not sync
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


}

应该避免锁定对象的引用变成另外的对象

锁定某个对象o,如果o的属性发生改变,不影响锁的使用,但是如果o变成另外一个对象,则锁定的对象发生改变,因为对象做锁的时候,它的锁的标记位在markword上面,如果锁的对象发生改变,则它的markword标记也发生改变了,就会导致程序出现问题
代码如下:

public class SyncSameObject {

     Object o = new Object();

    void m() {
        synchronized (o) {
            while (true) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());


            }
        }
    }

    public static void main(String[] args) {
       SyncSameObject t = new SyncSameObject();

        new Thread(t::m, "t1").start();

        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Thread t2 = new Thread(t::m, "t2");

        t.o = new Object(); //锁对象发生改变,所以t2线程得以执行,如果注释掉这句话,线程2将永远得不到执行机会
        t2.start();

    }
}
CAS的ABA问题理解

如果是基础类型,ABA问题无所谓,如果是引用类型就需要去解决了
ABA问题解决方式:加Version版本号控制,采用AtomicStampedReference。
ABA问题造成的后果: 假设有 A、B、C这三个对象,A这个对象指向B,B又指向C调用C的逻辑,如果采用CAS的方式,先让A指向C,然后对C对象里面的业务逻辑做一些更改,再让A重新指向B,然后另一个线程再直接通过A调用B然后再调用C,可能里面的执行结果,就受上一个线程的执行结果所干扰了。
其中AutomicInteger的incrementAndGet() 方法最终调用了Unsafe类的compareAndSwapInt方法
Unsafe类的JDK8版本实现:
直接操作内存

  • allocateMemory putXX freeMemory pageSize
    直接生成类实例
  • allocateInstance
    直接操作类或实例变量
    -objectFieldOffset
    -getInt
    -getObject
    CAS相关操作
    -compareAndSwapObject Int Long
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/686325.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号