Java Synchronization
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
- Don't provide "setter" methods — methods that modify fields or objects referred to by fields.
- Make all fields
finalandprivate. - 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 constructorprivateand construct instances in factory methods. - 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
final public class ImmutableRGB {
// Values must be between 0 and 255.
final private int red;
final private int green;
final private int blue;
final private String name;
private void check(int red,
int green,
int blue) {
if (red < 0 || red > 255
|| green < 0 || green > 255
|| blue < 0 || blue > 255) {
throw new IllegalArgumentException();
}
}
public ImmutableRGB(int red,
int green,
int blue,
String name) {
check(red, green, blue);
this.red = red;
this.green = green;
this.blue = blue;
this.name = name;
}
public int getRGB() {
return ((red << 16) | (green << 8) | blue);
}
public String getName() {
return name;
}
public ImmutableRGB invert() {
return new ImmutableRGB(255 - red,
255 - green,
255 - blue,
"Inverse of " + name);
}
}
Synchronized
Synchronized Method
public class SynchronizedCounter {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
}
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:
public class TestMethod {
public static void main(String[] args) {
final TestObject testObject = new TestObject(0);
new Thread() {
@Override
public void run() {
testObject.setValue(1);
}
}.start();
new Thread() {
@Override
public void run() {
testObject.getValue();
System.out.println("got value");
}
}.start();
}
}
class TestObject {
int value;
public TestObject(int value) {
this.value = value;
}
synchronized void setValue(int value) {
System.out.println("Entering the setvalue lock, waiting forever " + Thread.currentThread().getName());
this.value = value;
while (true) {
}
}
int getValue() {
return value;
}
}
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.
private Object lock = new Object();
private void someInputRelatedWork() {
synchronize(lock) { ...
}
}
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
longanddouble). - Reads and writes are atomic for all variables declared
volatile(includinglonganddoublevariables).
Java Synchronization的更多相关文章
- Java Performance Optimization Tools and Techniques for Turbocharged Apps--reference
Java Performance Optimization by: Pierre-Hugues Charbonneau reference:http://refcardz.dzone.com/refc ...
- 监视锁——Java同步的基本思想
翻译人员: 铁锚翻译时间: 2013年11月13日原文链接: Monitors – The Basic Idea of Java synchronization如果你上过操作系统课程,你就知道监视锁( ...
- 锁——Java同步的基本思想
翻译人员: 铁锚 翻译时间: 2013年11月13日 原文链接: Monitors – The Basic Idea of Java synchronization 如果你上过操作系统课程,你就知道 ...
- [Java基础] Java线程复习笔记
先说说线程和进程,现代操作系统几乎无一例外地采用进程的概念,进程之间基本上可以认为是相互独立的,共享的资源非常少.线程可以认为是轻量级的进 程,充分地利用线程可以使得同一个进程中执行多种任务.Java ...
- Java基础学习总结(80)——Java性能优化详解
让Java应用程序运行是一回事,但让他们跑得快就是另外一回事了.在面对对象的环境中,性能问题就像来势凶猛的野兽.但JVM的复杂性将性能调整的复杂程度增加了一个级别.这里Refcard涵盖了JVM in ...
- Thread Safety in Java(java中的线程安全)
Thread Safety in Java is a very important topic. Java provide multi-threaded environment support usi ...
- Top 8 Diagrams for Understanding Java
Reference: http://www.programcreek.com/2013/09/top-8-diagrams-for-understanding-java/ A diagram is s ...
- 垂直打击之JVM剖析
让Java应用程序运行是一回事,但让他们跑得快就是另外一回事了.在面对对象的环境中,性能问题就像来势凶猛的野兽.但JVM的复杂性将性能调整的复杂程度增加了一个级别.这里Refcard涵盖了JVM in ...
- Android 性能优化(20)多核cpu入门:SMP Primer for Android
SMP Primer for Android 1.In this document Theory Memory consistency models Processor consistency CPU ...
随机推荐
- as3 操作图片,获取,设置实际像素,扣除透明区域
private var a:Loader = new Loader(); private function test():void { a.load(new URLRequest("asse ...
- [笔记]GBDT理论知识总结
一. GBDT的经典paper:<Greedy Function Approximation:A Gradient Boosting Machine> Abstract Function ...
- 搞定:Enter passphrase for key提示
使用ssh-genkey生成公用key,但是自己使用时会多次提示,Enter passphrase for key,这儿给出如何解决. 在${HOME}/.bashrc中增加如下代码: alias a ...
- 浅析Java中synchronized与static synchronized
synchronized关键字 synchronized是进行同步处理而保证线程安全.在一个方法中,如果是方法内的私有变量,那个这个变量是线程安全的,但是类中的实例变量是可能会出现线程安全问题的,当多 ...
- Liferay中利用URL传参数
业务场景:现在有一个新闻系统,有两个页面,A是新闻列表页面/web/guest/home,B是新闻的详情页面/web/guest/newsview. 业务逻辑为:在A页面中,点击新闻的标题进入B页面, ...
- JavascriptS中的各结构的嵌套和函数
各位朋友大家好,上周更新给大家分享了JavaScript的入门知识及各种常用结构的用法,那么,本次更新博主就跟大家更深入的聊一聊JS各结构的嵌套用法,及JS中及其常用的一种结构--函数.以下为函数和循 ...
- 混合式app ionic2.x 手动搭建开发环境教程分享(nodejs,jdk,ant,androidsdk)
1.ionic简介 为什么选用ionic: 彻底开源且免费 性能优异 基于红的发紫的AngularJs 漂亮的UI 强大的命令行(基于更热门的nodejs) 开发团队非常活跃 ngCordova,将主 ...
- Spark入门实战
星星之火,可以燎原 Spark简介 Spark是一个开源的计算框架平台,使用该平台,数据分析程序可自动分发到集群中的不同机器中,以解决大规模数据快速计算的问题,同时它还向上提供一个优雅的编程范式,使得 ...
- 设计模式总结(Java)—— 适配器模式
适配器模式中引入了一个被称为适配器(Adapter)的包装类,而它所包装的对象称为适配者(Adaptee),即被适配的类.适配器的实现就是把客户类的请求转化为对适配者的相应接口的调用.也就是说:当客户 ...
- 【模板】Tarjan求强连通分量
有人说这篇博客不是很友好,所以我加了点解释,感觉是不是友好多了? dfn[u]表示节点u在dfs时被访问的次序. low[u]表示节点u能够追溯到的最远的祖先的dfn. ins[u]表示节点u是否在栈 ...