- 浏览: 252132 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (298)
- 工作感悟 (6)
- java基础 (23)
- 计算机硬件知识 (1)
- 计算机网络知识 (2)
- Struts (3)
- Srping (4)
- hibernate (0)
- ibatis (0)
- webservice (4)
- Thread (22)
- maven (5)
- ubuntu/linux/centos/redhat (46)
- SSO (1)
- ESB (0)
- 工作流 (0)
- oracle (15)
- 云计算 (1)
- hadoop (1)
- nosql (0)
- mysql (3)
- sqlserver (0)
- jquery (0)
- 分布式 (3)
- 集群 (0)
- 设计模式 (2)
- EJB (0)
- map (0)
- cache (5)
- Niginx+varnish+squid+Ats (14)
- Apache (0)
- 工作/职业规划 (0)
- Scala & Groovy (1)
- English (4)
- 数据结构/算法 (6)
- 开发工具 (5)
- 测试 (2)
- Exception (0)
- 定时器 (3)
- j2ee (2)
- 部署 (1)
- Openssl (1)
- 操作系统 (3)
- kvm (13)
- libvirt (5)
- PostgreSql (5)
- 虚拟化 (3)
- 概念理解 (1)
- virt-manager (1)
- RESTful (3)
- 其它 (4)
- ssh2 (14)
- windows (1)
- 房产 (2)
- svn (1)
- 手机 (1)
- ant (1)
- flume (2)
- sqoop (1)
- fastdfs (5)
- log4j (1)
- SPDY (1)
- mongodb (2)
- MQ (2)
- Mina (1)
- dubbo (4)
- PMP (1)
- Webshpere (2)
- jvm (1)
- Btrace (1)
- zookeeper (7)
- UML (1)
- spring cloud (6)
- spring boot (5)
- storm (0)
- 软件管理 (1)
- elasticsearch (1)
- 协议 (2)
- docker (1)
- 性能 (2)
- 安全 (1)
- 代码规范 (1)
- mqtt (1)
- lombok (1)
- 车联网 (1)
- kafka (1)
最新评论
volatile关键字相信了解Java多线程的读者都很清楚它的作用。volatile关键字用于声明简单类型变量,如int、float、boolean等数据类型。如果这些简单数据类型声明为volatile,对它们的操作就会变成原子级别的。但这有一定的限制。例如,下面的例子中的n就不是原子级别的:
package mythread;
public class JoinThread extends Thread
{
public static volatile int n = 0;
public void run()
{
for (int i = 0; i < 10; i++)
try
{
n = n + 1;
sleep(3); // 为了使运行结果更随机,延迟3毫秒
}
catch (Exception e)
{
}
}
public static void main(String[] args) throws Exception
{
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++)
// 建立100个线程
threads[i] = new JoinThread();
for (int i = 0; i < threads.length; i++)
// 运行刚才建立的100个线程
threads[i].start();
for (int i = 0; i < threads.length; i++)
// 100个线程都执行完后继续
threads[i].join();
System.out.println("n=" + JoinThread.n);
}
}
如果对n的操作是原子级别的,最后输出的结果应该为n=1000,而在执行上面积代码时,很多时侯输出的n都小于1000,这说明n=n+1不是原子级别的操作。原因是声明为volatile的简单变量如果当前值由该变量以前的值相关,那么volatile关键字不起作用,也就是说如下的表达式都不是原子操作:
n = n + 1;
n++;
如果要想使这种情况变成原子操作,需要使用synchronized关键字,如上的代码可以改成如下的形式:
package mythread;
public class JoinThread extends Thread
{
public static int n = 0;
public static synchronized void inc()
{
n++;
}
public void run()
{
for (int i = 0; i < 10; i++)
try
{
inc(); // n = n + 1 改成了 inc();
sleep(3); // 为了使运行结果更随机,延迟3毫秒
}
catch (Exception e)
{
}
}
public static void main(String[] args) throws Exception
{
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++)
// 建立100个线程
threads[i] = new JoinThread();
for (int i = 0; i < threads.length; i++)
// 运行刚才建立的100个线程
threads[i].start();
for (int i = 0; i < threads.length; i++)
// 100个线程都执行完后继续
threads[i].join();
System.out.println("n=" + JoinThread.n);
}
}
上面的代码将n=n+1改成了inc(),其中inc方法使用了synchronized关键字进行方法同步。因此,在使用volatile关键字时要慎重,并不是只要简单类型变量使用volatile修饰,对这个变量的所有操作都是原来操作,当变量的值由自身的上一个决定时,如n=n+1、n++等,volatile关键字将失效,只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如n = m + 1,这个就是原级别的。所以在使用volatile关键时一定要谨慎,如果自己没有把握,可以使用synchronized来代替volatile。
package mythread;
public class JoinThread extends Thread
{
public static volatile int n = 0;
public void run()
{
for (int i = 0; i < 10; i++)
try
{
n = n + 1;
sleep(3); // 为了使运行结果更随机,延迟3毫秒
}
catch (Exception e)
{
}
}
public static void main(String[] args) throws Exception
{
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++)
// 建立100个线程
threads[i] = new JoinThread();
for (int i = 0; i < threads.length; i++)
// 运行刚才建立的100个线程
threads[i].start();
for (int i = 0; i < threads.length; i++)
// 100个线程都执行完后继续
threads[i].join();
System.out.println("n=" + JoinThread.n);
}
}
如果对n的操作是原子级别的,最后输出的结果应该为n=1000,而在执行上面积代码时,很多时侯输出的n都小于1000,这说明n=n+1不是原子级别的操作。原因是声明为volatile的简单变量如果当前值由该变量以前的值相关,那么volatile关键字不起作用,也就是说如下的表达式都不是原子操作:
n = n + 1;
n++;
如果要想使这种情况变成原子操作,需要使用synchronized关键字,如上的代码可以改成如下的形式:
package mythread;
public class JoinThread extends Thread
{
public static int n = 0;
public static synchronized void inc()
{
n++;
}
public void run()
{
for (int i = 0; i < 10; i++)
try
{
inc(); // n = n + 1 改成了 inc();
sleep(3); // 为了使运行结果更随机,延迟3毫秒
}
catch (Exception e)
{
}
}
public static void main(String[] args) throws Exception
{
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++)
// 建立100个线程
threads[i] = new JoinThread();
for (int i = 0; i < threads.length; i++)
// 运行刚才建立的100个线程
threads[i].start();
for (int i = 0; i < threads.length; i++)
// 100个线程都执行完后继续
threads[i].join();
System.out.println("n=" + JoinThread.n);
}
}
上面的代码将n=n+1改成了inc(),其中inc方法使用了synchronized关键字进行方法同步。因此,在使用volatile关键字时要慎重,并不是只要简单类型变量使用volatile修饰,对这个变量的所有操作都是原来操作,当变量的值由自身的上一个决定时,如n=n+1、n++等,volatile关键字将失效,只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如n = m + 1,这个就是原级别的。所以在使用volatile关键时一定要谨慎,如果自己没有把握,可以使用synchronized来代替volatile。
发表评论
-
Java通过Executors提供四种线程池
2017-09-27 10:21 439Java通过Executors提供四种线程池,分别为: new ... -
并发线程组件 Amino
2013-07-23 13:29 663Amino CBB (Concurrent Building ... -
Java多线程之Semaphore
2013-07-17 16:12 561import java.util.ArrayL ... -
ThreadLocal的介绍(利用变量副本实现多线程访问同一变量)
2013-07-17 14:20 765早在Java 1.2推出之时,Ja ... -
ThreadGroup其实比ExecutorService更好
2013-07-17 13:32 673用java做抓取的时候免不了要用到多线程的了,因为要同时抓取多 ... -
Java多线程同步器
2013-07-12 17:00 837CyclcBarrier 在实际应用中,有时候需要多个线程 ... -
Java Thread.interrupt 害人! 中断JAVA线程
2013-07-12 16:37 750程序是很简易的。然而,在编程人员面前,多线程呈现出了一组新的难 ... -
Java多线程学习——Condition的使用
2013-07-12 14:36 789Condition 将 Object 监视器方法(wait、n ... -
java多线程设计wait
2013-07-12 14:30 662在Java中,这个机制的实 ... -
Monitor
2013-07-12 10:44 15021. 什么是Monitor? Monitor其实是一 ... -
处理 子线程的返回值
2013-07-08 14:19 819package com.jimmy.Thread.Conc ... -
ExecutorService的execute和submit方法
2013-07-05 17:21 940因为之前一直是用的exec ... -
Exchanger-兄弟线程的信息交换
2013-07-05 16:23 666如果两个线程在运行过程中需要交换彼此的信息,比如一个数据或者使 ... -
lockInterruptibly 和lock的区别
2013-06-26 16:36 839lockInterruptibly 与 lock比较区别在于 ... -
对synchronized(this)的一些理解
2013-06-26 10:18 649一、当两个并发线程访问同一个对象object中的这个synch ... -
java中的lock和synchronized区别
2013-06-26 10:02 5631、ReentrantLock 拥有Synchronized相 ... -
线程sleep,join,yield的区别
2013-06-21 17:37 4801.sleep() 使当前线程(即调用该方法的线程)暂停执行 ... -
初学Java多线程:慎重使用volatile关键字
2013-02-25 15:18 663学习Java多线程中会遇到使用volatile关键字的情况。v ... -
java之yield(),sleep(),wait()区别详解-备忘笔记
2013-02-25 14:32 6051、sleep() 使当前线程(即调用该方法的线程)暂停执行 ... -
Java Thread join() 的用法
2013-02-25 13:24 560Java Thread中, join() 方法主要是让调用改方 ...
相关推荐
java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java ...
volatile关键字相信了解Java多线程的读者都很清楚它的作用。volatile关键字用于声明简单类型变量,下面看一下为什么要慎重使用volatile关键字
Java并发编程:volatile关键字解析
volatile关键字基本介绍 volatile可以看成是synchronized的一种轻量级的实现,但volatile并不能完全代替synchronized,volatile有synchronized可见性的...另外,使用volatile还能确保变量不能被重排序,保证了有序性。
C/C++ 嵌入式 一些关键字: volatile关键字 Const关键字 static关键字 mutable 关键字
C语言中关键字volatile的作用,使用说明和例子
一个生动的例子,详解了Volatile关键字对变量的声明在不同编译环境下可能造成不同的结果
详细描述关于votatile关键字使用,可以帮助你加深对volatile关键字的理解和使用。
java volatile 关键字 学习
主要讲述java线程volatile关键字
volatile 的字面含义是易变的,那么将一个变量指示为volatile 是什么意思呢?是告诉编 译器这个变量是易变的?事实上也是如此。在多任务、中断等环境下,变量可能被其他的任 务改变,而编译器无法发现,volatile ...
java里的volatile关键字详解
深入理解 volatile 关键字.doc
volatile是java中的关键词之一,这篇文章主要给大家介绍了关于Java中volatile关键字的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
6vc中volatile关键字的应用共4页.pdf.zip
volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如 操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对...使用该关键字的例子如下: int volatile nVint;
java里的volatile关键字详解.pdf
C++Volatile关键字[参考].pdf
多方面解读Java中的volatile关键字.rar
java语言的volatile教程,java语言的volatile关键字到底怎么用