volatile

Volatile关键字详解

一个人想着一个人 提交于 2019-12-02 20:12:37
简介    在java中,每个线程有一块工作内存区,其中存放这被所有线程共享的主内存中变量值的拷贝。当线程执行时,它在自己的工作内存中操作这些变量。为了获取一个共享变量,一个线程先获取锁定并清除它的工作内存区,这就保证了该共享变量从所有的线程的共享主内存区正确的装入到线程的工作内存区,当线程解锁时保证该工作内存区的变量的值写回到共享主内存区。   线程工作内存和主内存的交互图如下:   从上图中可以看出,主内存和线程工作内存间的数据传输与线程工作内存和线程执行有一定的时间间隔,而且每次所消耗的时间可能还不相同,这样就存在线程操作的数据的不一致性。由于每个线程都有自己的线程工作内存,因此当一个线程改变自己工作内存中的数据的时候,对于其他系统来说可能是不可见的。因此,使用volatile关键字迫使所有的线程均读写主内存中对应的变量,从而使得volatile关键字修饰的变量在多线程间可见。   volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的。   声明为volatile的变量具有如下特性:   1、其他线程对变量的修改可以即时反映在当前线程中。   2、确保当前线程对volatile变量的修改,能即时的写回到共享主内存中,并被其他线程所见。   3、使用volatile修饰的变量,编译器会保证其有序性。 volatile分析    用在多线程

Session counter with HttpSessionListener and session count variable access

元气小坏坏 提交于 2019-12-02 20:10:41
问题 I saw an example with session counter in Sun's "Core Servlets and JavaServer Pages vol 2". Counter is simply build on HttpSessionListener and increments/decrements session count with sessionCreated / sessionDestroyed : public class SessionCounter implements HttpSessionListener { private int currentSessionCount = 0; public void sessionCreated(HttpSessionEvent event) { currentSessionCount++; } ... public int getTotalSessionCount() { return(totalSessionCount); } ... // counter decrement, self

多线程实现原理

依然范特西╮ 提交于 2019-12-02 19:55:29
JMM保证原子性、可见性、有序性 原子性 两个高级的字节码指令monitorenter和monitorexit,在java中对应的Synchronized来保证代码块内的操作是原子的 可见性 volatile 写操作的时候会多出一个lock前缀的汇编指令 MESI的缓存一致性协议,来保证多CPU下的各个高速缓存中的数据的 一致性 synchronized和final也可以实现可见性 有序性 volatile(禁止指令重排) 遵循as-if-serial语义 synchronized(同一时刻只允许一条线程操作) 内存屏障 通过下面三种方式的作用: 防止指令之间的重排序 保证数据的可见性 写屏障(store barrier) storestore barrier 强制所有在storestore内存屏障之前的所有执行,都要在该内存屏障之前执行,并发送缓存失效的信号 读屏障(load barrier) loadload barrier 强制所有在load barrier读屏障之后的load指令,都在loadbarrier屏障之后执行 全屏障(Full Barrier) 相当于storeload,是一个全能型的屏障 强制了所有在storeload barrier之前的store/load指令,都在该屏障之前被执行,所有在该屏障之后的的store/load指令,都在该屏障之后被执行

Java并发编程:线程池的使用

亡梦爱人 提交于 2019-12-02 19:48:27
转载自:http://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用   在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:   如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。   那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?   在Java中可以通过线程池来达到这样的效果。今天我们就来详细讲解一下Java的线程池,首先我们从最核心的ThreadPoolExecutor类中的方法讲起,然后再讲述它的实现原理,接着给出了它的使用示例,最后讨论了一下如何合理配置线程池的大小。   以下是本文的目录大纲:   一.Java中的ThreadPoolExecutor类   二.深入剖析线程池实现原理   三.使用示例   四.如何合理配置线程池的大小    若有不正之处请多多谅解,并欢迎批评指正。   请尊重作者劳动成果,转载请标明原文链接:   http://www.cnblogs.com/dolphin0520/p/3932921.html   一.Java中的ThreadPoolExecutor类   java.uitl

Java volatile and side-effects

南笙酒味 提交于 2019-12-02 19:47:43
Oracle's documentation on atomic access (at http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html ) says this: "a volatile variable establishes a happens-before relationship... . This means that ... when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change." I'm having trouble wrapping my head around that. I understand how volatile variables work (in >= Java 5), but I'm wondering how the java decides what side-affect "led up" to the change of a volatile variable. So I guess my

Can volatile but unfenced reads yield indefinitely stale values? (on real hardware)

好久不见. 提交于 2019-12-02 18:56:23
In answering this question a further question about the OP's situation came up that I was unsure about: it's mostly a processor architecture question, but with a knock-on question about the C++ 11 memory model as well. Basically, the OP's code was looping infinitely at higher optimization levels because of the following code (slightly modified for simplicity): while (true) { uint8_t ov = bits_; // bits_ is some "uint8_t" non-local variable if (ov & MASK) { continue; } if (ov == __sync_val_compare_and_swap(&bits_, ov, ov | MASK)) { break; } } where __sync_val_compare_and_swap() is GCC's atomic

线程同步 ——volatile

一个人想着一个人 提交于 2019-12-02 18:52:13
上一篇我们简单的使用了synchoronized实现线程同步,接下来简单的使用volatile实现线程同步。 public class ThreadCount { //如果去掉volatile就会出现错误 private static volatile int total; public static void main(String[] args) { Counter counter1 = new Counter(10); Counter counter2 = new Counter(20); Counter counter3 = new Counter(5); Counter counter4 = new Counter(10); Counter counter5 = new Counter(10); Counter counter6 = new Counter(20); counter1.start(); counter2.start(); counter3.start(); counter4.start(); counter5.start(); counter6.start(); } static class Counter extends Thread { private int i; Counter(int i) { this.i = i; } @Override

精确解释java的volatile之可见性、原子性、有序性(通过汇编语言)

我是研究僧i 提交于 2019-12-02 18:52:00
一、实验环境: 1、Idea代码编辑器 2、jdk1.8.0_92 3、win10_x64 二、易产生误解的Java字段Volatile volatile保证了可见性,但是并不保证原子性!!! 1.volatile关键字的两层语义   一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:   1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。   2)禁止进行指令重排序。 volatile的可见性,即任何时刻只要有任何线程修改了volatile变量的值,其他线程总能获取到该最新值。具体更多实现可以参阅缓存一致性协议。 2.那么volatile为什么又不能保证原子性呢? 以volatile int i = 10;i++;为例分析: i++实际为load、Increment、store三个操作。 某一时刻线程1将i的值load取出来,放置到cpu缓存中,然后再将此值放置到寄存器A中,然后A中的值自增1(寄存器A中保存的是中间值,没有直接修改i,因此其他线程并不会获取到这个自增1的值)。如果在此时线程2也执行同样的操作,获取值i==10,自增1变为11,然后马上刷入主内存。此时由于线程2修改了i的值,实时的线程1中的i==10的值缓存失效,重新从主内存中读取,变为11

Java并发编程:线程池的使用

左心房为你撑大大i 提交于 2019-12-02 18:36:19
在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:   如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。   那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?   在Java中可以通过线程池来达到这样的效果。今天我们就来详细讲解一下Java的线程池,首先我们从最核心的ThreadPoolExecutor类中的方法讲起,然后再讲述它的实现原理,接着给出了它的使用示例,最后讨论了一下如何合理配置线程池的大小。   以下是本文的目录大纲:   一.Java中的ThreadPoolExecutor类   二.深入剖析线程池实现原理   三.使用示例   四.如何合理配置线程池的大小    若有不正之处请多多谅解,并欢迎批评指正。   请尊重作者劳动成果,转载请标明原文链接:   http://www.cnblogs.com/dolphin0520/p/3932921.html   一.Java中的ThreadPoolExecutor类   java.uitl.concurrent.ThreadPoolExecutor类是线程池中最核心的一个类,因此如果要透彻地了解Java中的线程池,必须先了解这个类

C Primer Plus 第12章 12.7 ANSI C的类型限定词

て烟熏妆下的殇ゞ 提交于 2019-12-02 18:10:48
您已经知道一个变量是以它的类型与存储类表征的。C90增加了两个属性:不变性和易变性。这些属性是通过关键字const和volatile声明的,这样就创建了受限类型(qualified type)。C99标准添加了第三个限定词resrict,用以方便编译器优化。 C99授予类型限定词一个新属性:它们现在是幂等的(idempotent)!这听起来像一个强大的功能,其实只意味着可以在一个声明 中不止一次地使用同一限定词,多余的将被忽略掉: const const const int n = 6; //相当于const int n = 6; 例如,这使下列序列可以被接受: typedef const int zip; const zip q=8; 12.7.1 类型限定词const 回顾一下,如果变量声明中带有关键字const,则不能通过赋值、增量或减量运算来修改该变量的值。在与ANSI 编译器中,下面的代码将产生一个错误信息: const int nochange; //把m限定为常量 nochange = 12; //不允许 然而,可以初始化一个const变量。因此,下面的代码是正确的: const int nochange = 12; //可以 上面的声明使nochange成为一个只读变量。在初始化以后,不可以再改变它。 例如,可以用关键字const创建一组程序不可以改变的数据: