前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >两个线程对变量i进行加1操作,结果如何?

两个线程对变量i进行加1操作,结果如何?

作者头像
疯狂的KK
发布2020-06-18 16:54:18
1.7K0
发布2020-06-18 16:54:18
举报
文章被收录于专栏:Java项目实战

梳理博客,写到关于两个线程对变量i进行加1操作,结果如何?为什么?如何解决?首先分析问题,多线程环境对共享变量发生修改,经典的线程安全问题,通过解决问题的思路拓展。

1--错误的常规写法

代码语言:javascript
复制
public static int i=0;
public static void add(){
    i=i+1;
    action();
}
public static void action(){
    System.out.println("==>"+Thread.currentThread().getName()+":"+i);
}
public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(SysUserServiceImpl::add,"t1");
    Thread t2= new Thread(SysUserServiceImpl::add,"t2");
    t1.start();
    t2.start();
}
运行结果==>
==>t1:1
==>t2:2

==>t1:2
==>t2:1

==>t1:2
==>t2:2

每次运行结果不一致,多线程环境下,t1对共享内存中的i进行+1操作,但未将值刷新到主内存,此时恰好t2也对i取到还是0进行+1操作,使得最后结果i都为1,同理t1处理完为1,t2处理完为2。多次运行结果都不一致。

改进方法1 --同步锁

代码语言:javascript
复制
public class ThreadException {
    public static volatile int i=0;
    public static void add(){
        synchronized (ThreadException.class){
            i=i+1;
            action();
        }
    }
    public static void action(){
        System.out.println("==>"+Thread.currentThread().getName()+":"+i);
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(ThreadException::add,"t1");
        Thread t2= new Thread(ThreadException::add,"t2");
        t1.start();
        t2.start();

    }
}

优点:实现简单

缺点:加锁粒度大,性能低下,分布式环境,多JVM条件,synchronized失效,synchronized 只是本地锁,锁的也只是当前jvm下的对象,在分布式场景下,要用分布式锁

改进方法2 AtomicInteger

代码语言:javascript
复制
public class ThreadException {
    private static AtomicInteger num = new AtomicInteger(0);
    public static void add(){
        int i = num.getAndIncrement();
        action(i);
    }
    public static void action(int i){
        System.out.println("由"+i+"==>"+Thread.currentThread().getName()+":"+num);
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(ThreadException::add,"t1");
        Thread t2= new Thread(ThreadException::add,"t2");
        t1.start();
        t2.start();
    }
}

改进方法3 lock

代码语言:javascript
复制
public class ThreadException {
    public static volatile int i=0;
    public static void action(){
        System.out.println("==>"+Thread.currentThread().getName()+":"+i);
    }

    static Lock lock=new ReentrantLock();
    public static void inc() {
        lock.lock();
        try {
            Thread.sleep(1);
            i=i+1;
            action();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(ThreadException::inc,"t1");
        Thread t2= new Thread(ThreadException::inc,"t2");
        t1.start();
        t2.start();
    }
}

分布式锁:保证多个节点同步执行 实现方案:1。基于数据库,2.基于redis缓存,3.基于zookeeper

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 赵KK日常技术记录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档