synchronized和volatile关键字

synchronized

同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用 synchronized 修饰方法或者代码块。

volatile

用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的值。volatile很容易被误用,用来进行原子性操作。

以下两段程序演示了两者区别

package net.dp.volatileTest;

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 < 1000

	}
}

程序的运行结果是n小于1000.

原因:Java在创建线程的时候会为每一个线程分配线程当前的内存空间用来存放当前线程中的变量,存储在栈中;这些变量最终的值是存储在堆中。也就是说栈中会有堆中变量值的副本。volatile关键字是保证不同线程对该变量的访问是从堆中获取,拿到的是同一个变量的真实值不是栈中的副本。但是这并不能保证该操作是原子性的。在程序中n = n + 1操作就不是原子性的所以才会出错。

使用synchronized关键字解决该问题。

 

package net.dp.volatileTest;

public class JoinThread2 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 JoinThread2();
		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= " + JoinThread2.n);
	}

}

  

程序执行结果是1000 

使用synchronized关键字对自增操作修饰,保证了自增的原子操作。

  

时间: 2024-10-17 03:00:08

synchronized和volatile关键字的相关文章

synchronized、volatile关键字

synchronized还可以应用在静态方法上,如果这么写,则代表的是对当前.java文件对应的Class类加锁.看一下例子,注意一下printC()并不是一个静态方法: public class ThreadDomain25 { public synchronized static void printA() { try { System.out.println("线程名称为:" + Thread.currentThread().getName() + "在" +

synchronized锁定类方法、volatile关键字及其他

http://www.cnblogs.com/xrq730/p/4853578.html synchronized还可以应用在静态方法上,如果这么写,则代表的是对当前.java文件对应的Class类加锁.看一下例子,注意一下printC()并不是一个静态方法: public class ThreadDomain25 { public synchronized static void printA() { try { System.out.println("线程名称为:" + Threa

Java多线程6:synchronized锁定类方法、volatile关键字及其他

同步静态方法 synchronized还可以应用在静态方法上,如果这么写,则代表的是对当前.java文件对应的Class类加锁.看一下例子,注意一下printC()并不是一个静态方法: public class ThreadDomain25 { public synchronized static void printA() { try { System.out.println("线程名称为:" + Thread.currentThread().getName() + "在&

volatile关键字和synchronized关键字

volatile关键字: 可以用来修饰字段(成员变量),就是告知程序任何对该变量的访问均需要从共享内存中获取,而对它的改变必须同步刷新回共享内存,它能保证所有线程对变量访问的可见性. synchronized关键字: 可以修饰方法或以同步块的形式来进行使用,它主要确保多个线程在同一时刻,只能有一个线程处于方法或者同步块中,它保证了对变量访问的可见性和排他性. package com.baidu.nuomi.concurrent; /** * Created by sonofelice on 16

并发编程之ThreadLocal、Volatile、synchronized、Atomic关键字扫盲

前言 对于ThreadLocal.Volatile.synchronized.Atomic这四个关键字,我想一提及到大家肯定都想到的是解决在多线程并发环境下资源的共享问题,但是要细说每一个的特点.区别.应用场景.内部实现等,却可能模糊不清,说不出个所以然来,所以,本文就对这几个关键字做一些作用.特点.实现上的讲解. 1.Atomic 作用 对于原子操作类,Java的concurrent并发包中主要为我们提供了这么几个常用的:AtomicInteger.AtomicLong.AtomicBoole

并发编程之关键字(synchronized、volatile)

并发编程主要设计两个关键字:一个是synchronized,另一个是volatile.下面主要讲解这两个关键字,并对这两个关机进行比较. synchronized synchronized是通过JMV种的monitorenter和monitorexit指令实现同步.monitorenter指令是在编译后插入到同步代码的开始位置,而monitorexit插入到同步代码的结束位置和异常位置.每一个对象都与一个monitor相关联,当monitor被只有后,它将处于锁定状态. 当一个线程试图访问同步代

Java并发编程:volatile关键字解析(转)

volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以重获生机. volatile关键字虽然从字面上理解起来比较简单,但是要用好不是一件容易的事情.由于volatile关键字是与Java的内存模型有关的,因此在讲述volatile关键之前,我们先来了解一下与内存模型相关的概念和知识,然后分析了volatile关键字的实现原理,最后给出了几个使用vola

Java并发编程:volatile关键字解析

volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以重获生机. volatile关键字虽然从字面上理解起来比较简单,但是要用好不是一件容易的事情.由于volatile关键字是与Java的内存模型有关的,因此在讲述volatile关键之前,我们先来了解一下与内存模型相关的概念和知识,然后分析了volatile关键字的实现原理,最后给出了几个使用vola

volatile关键字及内存可见性

先看一段代码: package com.java.juc; public class TestVolatile { public static void main(String[] args) { ThreadDemo td = new ThreadDemo(); new Thread(td).start(); while(true){ if(td.isFlag()){ System.out.println("----------------"); break; } } } } cla