您的位置:首页 > 编程语言 > Java开发

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 in

the 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 the
volatile 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 are

objects 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: