Java-JUC(十三):现在有两个线程同时操作一个整数I,做自增操作,如何实现I的线程安全性?
问题分析:正如i在多线程中如果想实现i的多线程操作,必须i要使用volitle来保证其内存可见性,但是i++自增操作不具备原子性操作,因此需要对i++这段代码确保其原子性操作即可。
方案1:
使用ReetranLock实现i++的原子性操作。
private static volatile int i=0;
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch=new CountDownLatch(2);
Lock lock=new ReentrantLock();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try{
lock.lock();
i++;
}finally{
lock.unlock();
countDownLatch.countDown();
}
}
},"Thread-1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try{
lock.lock();
i++;
}finally{
lock.unlock();
countDownLatch.countDown();
}
}
},"Thread-2");
thread1.start();
thread2.start();
countDownLatch.await(); System.out.println(i);
}
方案2:
使用Semaphore实现i++的原子性操作。
private static volatile int i = 0;
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(2);
Semaphore semaphore = new Semaphore(1);
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
semaphore.release();
countDownLatch.countDown();
}
}, "Thread-1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
semaphore.release();
countDownLatch.countDown();
}
}, "Thread-2");
thread1.start();
thread2.start();
countDownLatch.await();
System.out.println(i);
}
当然也可以选择sychronized方式实现。
Java-JUC(十三):现在有两个线程同时操作一个整数I,做自增操作,如何实现I的线程安全性?的更多相关文章
- Java CAS同步机制 原理详解(为什么并发环境下的COUNT自增操作不安全): Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性。
精彩理解: https://www.jianshu.com/p/21be831e851e ; https://blog.csdn.net/heyutao007/article/details/19 ...
- Java中如何把两个数组合并为一个
在Java中,如何把两个String[]合并为一个? 看起来是一个很简单的问题.但是如何才能把代码写得高效简洁,却还是值得思考的.这里介绍四种方法,请参考选用. 一.apache-commons 这是 ...
- Java实现把两个数组合并为一个的方法总结
本文实例讲述了Java实现把两个数组合并为一个的方法.分享给大家供大家参考,具体如下: 在Java中,如何把两个String[]合并为一个? 看起来是一个很简单的问题.但是如何才能把代码写得高效简洁, ...
- java 写一个"HelloJavaWorld你好世界"输出到操作系统文件Hello.txt文件中
package com.beiwo.homework; import java.io.File; import java.io.FileOutputStream; import java.io.IOE ...
- Java反射机制demo(六)—获得并操作一个类的属性
Java反射机制demo(六)—获得并操作一个类的属性 获得并操作一个类的属性?! 不可思议啊,一个类的属性一般都是私有成员变量啊,private修饰符啊! 但是毫无疑问,这些东西在Java的反射机制 ...
- Java - "JUC线程池" ThreadPoolExecutor原理解析
Java多线程系列--“JUC线程池”02之 线程池原理(一) ThreadPoolExecutor简介 ThreadPoolExecutor是线程池类.对于线程池,可以通俗的将它理解为"存 ...
- Java - "JUC线程池" 线程状态与拒绝策略源码分析
Java多线程系列--“JUC线程池”04之 线程池原理(三) 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基本概念"中,我们介绍过,线程有5种状态:新建 ...
- Java - "JUC" ReentrantLock获取锁
[Java并发编程实战]-----“J.U.C”:ReentrantLock之一简介 ReentrantLock介绍 ReentrantLock是一个可重入的互斥锁,又被称为“独占锁”. 顾名思义,R ...
- Java - "JUC"之Condition源码解析
Java多线程系列--“JUC锁”06之 Condition条件 概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition ...
随机推荐
- C#中多集合组合实现
C#中多集合组合使用方法,主要用到 Enumerable.Join方法 var skuInfoList = new Dictionary<int, List<long>>(); ...
- SQL LISTAGG 合并行
LISTAGG Syntax 语法 listagg_overflow_clause::= Purpose For a specified measure, LISTAGG orders data w ...
- Vi 和 Vim 编辑器详细使用方法
学习linux的一项必会技能,熟练使用vi/vim编辑器那便最重要的了.不过一堆操作看的也是太头疼了,以下整理了些常用到的命令. 工作模式 vi编辑界面有三种不同的工作模式,分别为命令模式.输入模式. ...
- 21.centos7基础学习与积累-007-远程连接
从头开始积累centos7系统运用 大牛博客:https://blog.51cto.com/yangrong/p5 IP地址: 互联网上的计算机 都会有一个唯一的32位的地址,ip地址,我们访问服务器 ...
- Guava Cache 工具类
maven依赖 <dependency> <groupId>com.google.guava</groupId> <artifactId>guava&l ...
- list去重,String[]去重,String[]去空,StringBuffer去重,并且以','隔开,list拆分
1.// 删除ArrayList中重复元素 public static void removeDuplicate(List list) { HashSet h = new HashSet(list); ...
- 状压dp之位运算
## 一.知识 1.我们知道计算机中数据由二进制数存储,一个二进制数的一位就是计算机中数据的最小单位bit,我们有一种运算符可直接对二进制数进行位运算,所以它的速度很快. 2.C++中的位运算符有6种 ...
- gson之将对象转化成json字符串的方法
public class GsonUtil { /** * 将object对象转成json格式字符串 */ public static String toJson(Object object) { G ...
- 《CoderXiaoban团队》实验十 团队作业6:团队项目系统设计改进与详细设计
实验十 团队作业6:团队项目系统设计改进与详细设计 项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 实验十 团队作业6:团队项目系统设计改进与详细设计 团队名称 Code ...
- Java线程池(ExecutorService)使用
一.前提 /** * 线程运行demo,运行时打出线程id以及传入线程中参数 */ public class ThreadRunner implements Runnable { private fi ...