Volatile

Since Java 5 the volatile keyword guarantees more than just the reading from and writing to main memory of variables. Actually, the volatile keyword guarantees this:

  • If Thread A writes to a volatile variable and Thread B subsequently reads the same volatile variable, then all variables visible to Thread A before writing the volatile variable, will also be visible to Thread B after it has read the volatile variable.

  • The reading and writing instructions of volatile variables cannot be reordered by the JVM (the JVM may reorder instructions for performance reasons as long as the JVM detects no change in program behaviour from the reordering). Instructions before and after can be reordered, but the volatile read or write cannot be mixed with these instructions. Whatever instructions follow a read or write of a volatile variable are guaranteed to happen after the read or write.

Volatile is not enough to guarantee the thread safety as it cannot protect the non-atomic operations, like counter++

If two threads are both reading and writing to a shared variable, then using the volatile keyword for that is not enough. You need to use a synchronized in that case to guarantee that the reading and writing of the variable is atomic. Reading or writing a volatile variable does not block threads reading or writing.

In case only one thread reads and writes the value of a volatile variable and other threads only read the variable, then the reading threads are guaranteed to see the latest value written to the volatile variable. Without making the variable volatile, this would not be guaranteed.

Immutable Objects

final fields, which cannot be modified after the object is constructed, can be safely read through non-synchronized methods, once the object is constructed

Rules specified in https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html

  1. Don't provide "setter" methods — methods that modify fields or objects referred to by fields.
  2. Make all fields final and private.
  3. Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods.
  4. If the instance fields include references to mutable objects, don't allow those objects to be changed:
    • Don't provide methods that modify the mutable objects.
    • Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.

An example of Immutable Obejct

  1. final public class ImmutableRGB {
  2.  
  3. // Values must be between 0 and 255.
  4. final private int red;
  5. final private int green;
  6. final private int blue;
  7. final private String name;
  8.  
  9. private void check(int red,
  10. int green,
  11. int blue) {
  12. if (red < 0 || red > 255
  13. || green < 0 || green > 255
  14. || blue < 0 || blue > 255) {
  15. throw new IllegalArgumentException();
  16. }
  17. }
  18.  
  19. public ImmutableRGB(int red,
  20. int green,
  21. int blue,
  22. String name) {
  23. check(red, green, blue);
  24. this.red = red;
  25. this.green = green;
  26. this.blue = blue;
  27. this.name = name;
  28. }
  29.  
  30. public int getRGB() {
  31. return ((red << 16) | (green << 8) | blue);
  32. }
  33.  
  34. public String getName() {
  35. return name;
  36. }
  37.  
  38. public ImmutableRGB invert() {
  39. return new ImmutableRGB(255 - red,
  40. 255 - green,
  41. 255 - blue,
  42. "Inverse of " + name);
  43. }
  44. }

Synchronized

Synchronized Method

  1. public class SynchronizedCounter {
  2. private int c = 0;
  3.  
  4. public synchronized void increment() {
  5. c++;
  6. }
  7.  
  8. public synchronized void decrement() {
  9. c--;
  10. }
  11.  
  12. public synchronized int value() {
  13. return c;
  14. }
  15. }

First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.

Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.

Synchronized on methods would block the whole object, like synchronized (this) { }.

if the setValue() method in a class is synchronized but getValue() method is not, then while a thread enters the setValue() method block, other threads could also enter getValue() method block at the same time. If getValue() method is also synchronized, then only one thread could enter one of the two methods at the same time. Test codes are:

  1. public class TestMethod {
  2. public static void main(String[] args) {
  3. final TestObject testObject = new TestObject(0);
  4.  
  5. new Thread() {
  6. @Override
  7. public void run() {
  8. testObject.setValue(1);
  9. }
  10. }.start();
  11.  
  12. new Thread() {
  13. @Override
  14. public void run() {
  15. testObject.getValue();
  16. System.out.println("got value");
  17. }
  18. }.start();
  19.  
  20. }
  21. }
  22.  
  23. class TestObject {
  24. int value;
  25.  
  26. public TestObject(int value) {
  27. this.value = value;
  28. }
  29.  
  30. synchronized void setValue(int value) {
  31. System.out.println("Entering the setvalue lock, waiting forever " + Thread.currentThread().getName());
  32. this.value = value;
  33. while (true) {
  34.  
  35. }
  36. }
  37.  
  38. int getValue() {
  39. return value;
  40. }
  41. }

Synchronized Block

Blocks do have advantages over methods, most of all in flexibility because you can use other object as lock whereas syncing the method would lock the complete class. This is usually the safest way to do the sunchronization.

  1. private Object lock = new Object();
  2.  
  3. private void someInputRelatedWork() {
  4.  
  5. synchronize(lock) { ...
  6.  
  7. }
  8.  
  9. }

Synchronized class

synchronized (MyClass.class) { } means lock on all the objects instantiated from the MyClass.class.

Synchronized Static Method

Since a static method has no associated object, the synchronized keyword lock on the class instead of the object?

The worst solution is to put the "synchronized" keywords on the static methods, which means it will lock on all instances of this class.

One point you have to be careful about (several programmers generally fall in that trap) is that there is no link between synchronized static methods and sync'ed non static methods, ie:

class A {

static synchronized f() {...}

synchronized g() {...} #

}

Main:

A a = new A();

Thread 1:

A.f();

Thread 2:

a.g();

f() and g() are not synchronized with each other and thus can execute totally concurrently.

You might wonder what happens when a static synchronized method is invoked, since a static method is associated with a class, not an object. In this case, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.

Atomic Access

An atomic action is one that effectively happens all at once. An atomic action cannot stop in the middle: it either happens completely, or it doesn't happen at all. No side effects of an atomic action are visible until the action is complete.

  • Reads and writes are atomic for reference variables and for most primitive variables (all types except long and double).
  • Reads and writes are atomic for all variables declared volatile (including long and double variables).

Java Synchronization的更多相关文章

  1. Java Performance Optimization Tools and Techniques for Turbocharged Apps--reference

    Java Performance Optimization by: Pierre-Hugues Charbonneau reference:http://refcardz.dzone.com/refc ...

  2. 监视锁——Java同步的基本思想

    翻译人员: 铁锚翻译时间: 2013年11月13日原文链接: Monitors – The Basic Idea of Java synchronization如果你上过操作系统课程,你就知道监视锁( ...

  3. 锁——Java同步的基本思想

    翻译人员: 铁锚 翻译时间: 2013年11月13日 原文链接:  Monitors – The Basic Idea of Java synchronization 如果你上过操作系统课程,你就知道 ...

  4. [Java基础] Java线程复习笔记

    先说说线程和进程,现代操作系统几乎无一例外地采用进程的概念,进程之间基本上可以认为是相互独立的,共享的资源非常少.线程可以认为是轻量级的进 程,充分地利用线程可以使得同一个进程中执行多种任务.Java ...

  5. Java基础学习总结(80)——Java性能优化详解

    让Java应用程序运行是一回事,但让他们跑得快就是另外一回事了.在面对对象的环境中,性能问题就像来势凶猛的野兽.但JVM的复杂性将性能调整的复杂程度增加了一个级别.这里Refcard涵盖了JVM in ...

  6. Thread Safety in Java(java中的线程安全)

    Thread Safety in Java is a very important topic. Java provide multi-threaded environment support usi ...

  7. Top 8 Diagrams for Understanding Java

    Reference: http://www.programcreek.com/2013/09/top-8-diagrams-for-understanding-java/ A diagram is s ...

  8. 垂直打击之JVM剖析

    让Java应用程序运行是一回事,但让他们跑得快就是另外一回事了.在面对对象的环境中,性能问题就像来势凶猛的野兽.但JVM的复杂性将性能调整的复杂程度增加了一个级别.这里Refcard涵盖了JVM in ...

  9. Android 性能优化(20)多核cpu入门:SMP Primer for Android

    SMP Primer for Android 1.In this document Theory Memory consistency models Processor consistency CPU ...

随机推荐

  1. Access SQL实现连续及不连续Rank排名

    一.关于起因 在Excel中我们经常使用Rank函数对数据进行排名操作.而在Access中我们要进行排名是找不到这个Rank函数的,此时我们需要自己书写VBA代码或者建立SQL查询来完成排序操作. 今 ...

  2. Android开发艺术1之Activity的生命周期

    作为<Android开发艺术探索>这本书的第一篇博客,我就多说几句.本系列博客旨在对书中相关内容进行解读,简化,提供一个入门到提高的流程.不敢说书评,也不能说教程,只希望对有些人有帮助就好 ...

  3. html/css/javascript的含义、作用及理解

    HTML(HyperText Markup Language/超文本标记语言) 含义:HTML是一种用于创建网页的标准标记语言. 作用:页面内可以包含图片.链接,甚至音乐.程序等非文字元素. 理解:主 ...

  4. 这个demo是为解决IQKeyboardManager和Masonry同时使用时,导航栏上移和make.right失效的问题

    原文链接在我的个人博客主页 (一).引言: 在 IQKeyboardManager 和 Masonry 同时使用时,导航栏上移和make.right失效等问题多多. 其实我们完美的效果应该是这样的:* ...

  5. require.js疑惑

    昨天小颖分享了一篇require.js入门 ,今天小颖发现了一个很郁闷的问题,希望大神们帮小颖解释下到底是什么原理才能出现以下的现象,其实小颖昨天也有问过园友里的一位帅锅,只是他解释的小颖没太明白.嘻 ...

  6. 你不得不知的逻辑或(||)与(&&)非(!)

    最近重新翻开原生JS,又得到很多不同的体会,虽然现在开发框架那么多,但很多思想都还是离不开原生的基础.今天呢,我就根据自己的学习总结一下逻辑与(&&)和(逻辑或(||)和逻辑非(!). ...

  7. Java容器的各种总结

    Java容器指的是List,Set,Map这些类.由于翻译的问题,问到集合,Collection这些指的都是它们几个. List ArrayList 随机访问快 LinkedList 插入删除快 这个 ...

  8. Java Script 字符串操作

    JS中常用几种字符串操作: big() small() bold() fontcolor() fontsize() italics() strike() link() charAt() charCod ...

  9. Real-time 节点

    Real-time 节点 Real-time 节点提供一个实时索引.通过这些节点索引的数据提供查询.real-time节点将定期将他们收集的数据转移到同一跨域时间的Historical节点. 使用zo ...

  10. AngularJS创建新指令 - 函数功能

    首先先介绍下AngularJS指令下的几种函数 Link函数和Scope 指令生成出的模板其实没有太多意义,除非它在特定的scope下编译.默认情况下,指令并不会创建新的子scope.更多的,它使用父 ...