两个线程对变量i进行加1操作,结果如何?
【摘要】 梳理博客,写到关于两个线程对变量i进行加1操作,结果如何?为什么?如何解决?首先分析问题,多线程环境对共享变量发生修改,经典的线程安全问题,通过解决问题的思路拓展。1–错误的常规写法public static int i=0;public static void add(){ i=i+1; action();}public static void action(){ Sy...
梳理博客,写到关于两个线程对变量i进行加1操作,结果如何?为什么?如何解决?首先分析问题,多线程环境对共享变量发生修改,经典的线程安全问题,通过解决问题的思路拓展。
1–错误的常规写法
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 --同步锁
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
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
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
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)