java多线程总结四:volatile、synchronized示例
1、synchronized保证同步
先看一个生成偶数的类
- <span style="font-size:16px;">package demo.thread;
- /**
- *这是一个int生成器的抽象类
- *
- */
- public abstract class IntGenerator {
- private volatile boolean canceled = false;
- public abstract int next();
- public void cancel() {
- canceled = true;
- }
- public boolean isCanceled() {
- return canceled;
- }
- }
- </span>
- <span style="font-size:16px;">/*
- * 产生偶数
- */
- class EvenGenerator extends IntGenerator {
- private int currentEvenValue = 0;
- String s = "";
- @Override
- public int next() {
- <span style="color:#ff0000;">synchronized </span>(s) {
- ++currentEvenValue;
- ++currentEvenValue;
- return currentEvenValue;
- }
- }
- // //这样也可以
- // public <span style="color:#ff0000;">synchronized </span>int next() {
- // ++currentEvenValue;
- // ++currentEvenValue;
- // return currentEvenValue;
- // }
- }</span>
注意到在产生偶数是要加同步锁,否则可能线程1刚好执行了一句++currentEvenValue;操作,就被线程2抢去了cpu,此时线程2执行return currentEvenValue;这时返回的就是一个奇数。加synchronized
就是两个线程同时只能一个线程执行synchronized 块的代码。
测试代码:
- <span style="font-size:16px;">package demo.thread;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- /*
- * 消费数字
- */
- public class EvenChecker implements Runnable {
- private IntGenerator generator;
- private final int id;
- public EvenChecker(IntGenerator g, int ident) {
- generator = g;
- id = ident;
- }
- public void run() {
- while (!generator.isCanceled()) {
- int val = generator.next();
- if (val % 2 != 0) {//如果不是偶数
- System.out.println(val + " not enen!");
- generator.cancel();
- }
- }
- }
- public static void test(IntGenerator gp, int count) {
- ExecutorService exec = Executors.newCachedThreadPool();
- for (int i = 0; i < count; i++)
- exec.execute(new EvenChecker(gp, i));
- exec.shutdown();
- }
- public static void test(IntGenerator gp) {
- test(gp, 10);
- }
- public static void main(String[] args) {
- test(new EvenGenerator());
- }
- }</span>
分析:如果产生偶数的类未加synchronized,那么测试程序将会出现奇数导致退出程序。
2、volatile表示原子性,可见性。
对于多个线程之间共享的变量,每个线程都有自己的一份拷贝,当线程1改变变量值时,其他线程并不马上知道该变量值改变了,volatile就保证了变量值对各个线程可见,一个线程改变该值,马上其他线程中该值也改变。原子性表明操作不可中断,如基本变量赋值。
代码示例:
- <span style="font-size:16px;">package demo.thread;
- public class VolatileDemo implements Runnable {
- private volatile int i = 0;//volatile设置可见性
- public synchronized int getValue() {
- return i;
- }
- private synchronized void enenIncrement() {
- i++;
- i++;
- }
- @Override
- public void run() {
- while (true)
- enenIncrement();
- }
- public static void main(String[] args) {
- VolatileDemo at = new VolatileDemo();
- new Thread(at).start();
- while (true) {
- int val = at.getValue();
- if (val % 2 != 0) {//出现奇数,退出程序
- System.out.println(val+" is not enen!");
- System.exit(0);
- }
- }
- }
- }
- </span>
注意i++操作并不是原子行操作,getValue() 方法也要加synchronized 。
java多线程总结四:volatile、synchronized示例的更多相关文章
- Java多线程(四)—— synchronized关键字续
1.synchronized原理 在java中,每一个对象有且仅有一个同步锁.这也意味着,同步锁是依赖于对象而存在.当我们调用某对象的synchronized方法时,就获取了该对象的同步锁.例如,sy ...
- Java多线程核心技术(四)Lock的使用
本文主要介绍使用Java5中Lock对象也能实现同步的效果,而且在使用上更加方便. 本文着重掌握如下2个知识点: ReentrantLock 类的使用. ReentrantReadWriteLock ...
- Java多线程(四)java中的Sleep方法
点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...
- “全栈2019”Java多线程第四章:设置和获取线程名称
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- java多线程之内存可见性-synchronized、volatile
1.JMM:Java Memory Model(Java内存模型) 关于synchronized的两条规定: 1.线程解锁前,必须把共享变量的最新值刷新到主内存中 2.线程加锁时,将清空工作内存中共享 ...
- java多线程中的volatile和synchronized
package com.chzhao; public class Volatiletest extends Thread { private static int count = 0; public ...
- java多线程系列(四)---Lock的使用
Lock的使用 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理 ...
- java多线程(3)---synchronized、Lock
synchronized.Lock 一.概述 1.出现线程不安全的原因是什么? 如果我们创建的多个线程,存在着共享数据,那么就有可能出现线程的安全问题:当其中一个线程操作共享数据时,还未操作完成,另外 ...
- java多线程系列(四)---ReentrantLock的使用
Lock的使用 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理 ...
- java多线程:线程同步synchronized(不同步的问题、队列与锁),死锁的产生和解决
0.不同步的问题 并发的线程不安全问题: 多个线程同时操作同一个对象,如果控制不好,就会产生问题,叫做线程不安全. 我们来看三个比较经典的案例来说明线程不安全的问题. 0.1 订票问题 例如前面说过的 ...
随机推荐
- Hadoop,HBase,Zookeeper源码编译并导入eclipse
基本理念:尽可能的参考官方英文文档 Hadoop: http://wiki.apache.org/hadoop/FrontPage HBase: http://hbase.apache.org/b ...
- HDU 3635 并查集+路径压缩+记录每个点移动次数
题意: 给定n个点 oper个操作 每个点有1个龙珠 下面2种操作: T u v 把u点所有龙珠搬到v Q u 问u点当前所在城市 u点所在城市有几个龙珠 u点被移动几次 思路: 并查集可以求出 u ...
- java正则表达式入门基础
一.正则表达式术语 1)元字符 : 非一般字符,具有某种意义的字符.如 : \bX : \b边界符, 以 X开始的单词 2) 常用 : \d : 匹配一个数字 : \d , 匹配至少一个以上数字 \ ...
- HDU 5289 Assignment(2015 多校第一场二分 + RMQ)
Assignment Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total ...
- HDU 4608 I-number(模拟)
I-number Time Limit: 5000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描写叙述 The I-number of x is defined t ...
- 01---HTML整理
1.前端: 不同设备的适配 显示-->性能优化 某些计算任务 html5 2.xml: 传输数据 保存配置文件 3.乱码是 ...
- 《SAS编程与数据挖掘商业案例》学习笔记之十七
继续读书笔记,本次重点sas sql语句,因为sql内容多且复杂,本文仅仅介绍商业应用中经常使用的而且easy出错的地方,内容包含:单表操作.多表关联.子查询以及merge和join的差别 1.单表操 ...
- TCP/IP协议原理与应用笔记12:单播、多播和广播地址(目的地址)
根据数据接收者的接收范围,将目的地址分为单播.多播.广播. 这里目的地址的划分主要针对的是 物理地址 和 IP地址,没有涉及到端口地址,因为主要针对标识通信节点的地址(物理地址 和 IP地址)而言,和 ...
- Android(java)学习笔记124:Android权限大全
访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES读取或写入登记check-in数据库属性表的权限 获取错略位置 android.permissio ...
- android百度地图定位开发
一.activity import android.app.Activity; import android.graphics.Point;import android.graphics.PointF ...