java并发基础之The volatile keyword
2016-03-19 16:08
633 查看
java并发基础之The volatile keyword
Why synchronized?
One of the biggest changes in concurrent programming in recent years has been inthe realm of hardware. It wasn’t that many years ago that a working programmer
could go for years on end without encountering a system that had more than one or
at most two processing cores. It was thus possible to think of concurrent programming as being about the timesharing of the CPU—threads swapping on and off a single core.
Today, anything larger than a mobile phone has multiple cores, so the mental
model should be different too, encompassing multiple threads all running on different cores at the same physical moment (and potentially operating on shared data).
You can see this in figure 4.4. For efficiency, each thread that is running simultaneously
may have its own cached copy of data being operated on. With this picture in
mind, let’s turn to the question of the choice of keyword used to denote a locked section or method.
We asked earlier, what is it that’s being synchronized in the code in listing 4.1? The
answer is: The memory representation in different threads of the object being locked is what
is being synchronized. That is, after the
synchronized block (or method) has completed, any and all changes that were made
to the object being locked are flushed back
to main memory before the lock is released,
as illustrated in figure 4.5.
In addition, when a synchronized block
is entered, then after the lock has been acquired, any changes to the locked object are
read in from main memory, so the thread with the lock is synchronized to main memory’s view of the object before the code in the locked section begins to execute.
The volatile keyword
Java has had thevolatile keyword since the dawn of time (Java 1.0), and it’s used as a
simple way to deal with the synchronization of object fields, including primitives. The
following rules govern a volatile field:
■ The value seen by a thread is
always reread from main memory before use.
■ Any value written by a thread is
always flushed through to main memory before
the instruction completes.
This can be thought of as acting like a tiny little synchronized
block around the operation. It allows the programmer to write simplified code, but at the cost of the extra
flushes on every access. Notice also that the volatile variable doesn’t introduce any
locks, so you can’t deadlock by using volatile variables.
One slightly more subtle consequence of volatile variables is that for true threadsafety, a volatile variable should
only be used to model a variable where writes to the variable don’t depend on the current state (the read state) of the variable. For cases where the current state matters, you must always introduce a lock to be completely safe.
Immutability
One technique that can be of great value is the use of immutable objects. These areobjects that either have no state, or that have only final fields (which must therefore
be populated in the constructors of the objects). These are always safe and live,
because their state can’t be mutated, so they can never be in an inconsistent state.
One problem is that any values that are required to initialize a particular object
must be passed into the constructor. This can lead to unwieldy constructor calls, with
many parameters. Alternatively, many coders use a FactoryMethod instead. This can
be as simple as using a static method on the class, instead of a constructor, to produce new objects. The constructors are usually made protected or private, so that
the static FactoryMethods are the only way of instantiating.
This still has the problem of potentially needing many parameters to be passed in to
the FactoryMethod. This isn’t always very convenient, especially when you may need
to accumulate state from several sources before creating a new immutable object.
To solve this, you can use the Builder pattern. This is a combination of two constructs: a static inner class that implements a generic builder interface, and a private
constructor for the immutable class itself.
The static inner class is the builder for the immutable class, and it provides the
only way that a developer can get hold of new instances of the immutable type. One
very common implementation is for the Builder class to have exactly the same fields
as the immutable class, but to allow mutation of the fields.
This listing shows how you might use this to model a microblogging update (again,
building on the earlier listings in this chapter).
public interface ObjBuilder<T> { T build(); } public class Update { private final Author author; private final String updateText; private Update( Builder b_ ) { author = b_.author; updateText = b_.updateText; } public static class Builder implements ObjBuilder<Update> { private Author author; private String updateText; public Builder author( Author author_ ) { author = author_; return(this); } public Builder updateText( String updateText_ ) { updateText = updateText_; return(this); } public Update build() { return(new Update( this ) ); } } }
With this code, you could then create a new Update object like this:
Update.Builder ub = new Update.Builder(); Update u = ub.author(myAuthor).updateText("Hello").build();
One last point about immutable
objects—the final keyword only applies
to the object directly pointed to. As you
can see in figure 4.6, the reference to the
main object can’t be assigned to point at
object 3, but within the object, the reference to 1 can be swung to point at object 2.
Another way of saying this is that a final
reference can point at an object that has
nonfinal fields.
Immutability is a very powerful technique, and you should use it whenever feasible.
Sometimes it’s just not possible to develop efficiently with only immutable objects,
because every change to an object’s state requires a new object to be spun up. So we’re
left with the necessity of dealing with mutable objects.
读书笔记:The Well-Grounded Java Develope
相关文章推荐
- Java时间转换成ISO8601格林威治天文台的标准时间
- Eclipse开发STM32出现找不到函数的情况的解决方法
- [心得]Java开发中的小心得
- Java并发编程:Lock
- 深入理解Java之集合框架
- Spring Security 引用数据库管理用户权限-----login.jsp 提示"用户名或密码错误"
- 跟我学Spring3(8.2):对ORM的支持之集成Hibernate3
- Java线程池的测试和分析
- Eclipse加入PHP插件并支持PHP自动提示
- [MAVEN]一、maven入门之软件的下载及配置到Eclipse中
- Eclipse真机测试注意事项
- spring入门(12)-spring与hibernate整合完成增删改查的操作(继承HibernateDaoSupport调用hibernateTemplate类)
- spring入门(11)-spring与hibernate整合完成增删改查的操作(封装HibernateTemplate模版类对象)
- java中编码
- Java基础2
- java类加载资源的问题
- Java中获取键盘事件
- Spring ResourceLoader.getResource() & getResources()的理解
- java中静态代码块的用法 static用法详解
- 在Eclipse中设置文件的默认打开方式