答案:When multiple threads are interacting with an object, controls need to be in place to ensure that the threads don’t adversely affect one another. This chapter deals with issues that can introduce subtle errors in your application. An application that fails to safely control concurrent access can work properly most of the time—maybe nearly all the time—but will occasionally produce erroneous results. This makes the understanding and disciplined use of the information in this chapter critical to writing truly thread-safe applications that work properly all the time.
如果你的系统出现了莫名其妙的问题,很有可能是并发访问的问题哦
volatile Member Variable Modifier
The Java Language Specification indicates that for optimal speed, individual threads are permitted to keep a working copy of shared member variables and only reconcile them with the shared original occasionally. To be more accurate, the word “occasionally” in the last sentence should be replaced with “when a thread enters or leaves a synchronized block of code.” I’ll tell you more about synchronized blocks later in this chapter. When only one thread is interacting with the member variables of an object, this optimization works very well and can allow for faster execution. When two (or more) threads are simultaneously working with an object, care must be taken to ensure that changes made to a shared member variable by one thread are seen by the other.
Java规范中说明,为了优化速度,每个线程都拥有共享成员变量的一个拷贝,当线程开始或结束一个同步代码块时,才回写变量值。当单线程时,这种机制很好的工作,可以获得更高的性能,但是多个线程协同工作时,必须考虑,被一个线程改变的公共变量要被其他线程知道。
The volatile keyword is used as a modifier on member variables to force individual threads to reread the variable’s value from shared memory every time the variable is accessed. In addition, individual threads are forced to write changes back to shared memory as soon as they occur. This way, two different threads always see the same value for a member variable at any particular time. Chances are that most of you expected this behavior from the Java VM already. In fact, many experienced Java developers don’t understand when the use of volatile is necessary.
Volatile关键字,如果用来修饰成员变量,则易做图每个线程每次访问这个变量都要重新读取,每次改变变量值时都要尽快回写。这样,两个不同的线程在特定时间总能获得相同的变量值
Use volatile on member variables that can be accessed by two or more threads unless all the threads access the variables within synchronized blocks of code. If a member variable remains constant after construction (it is read-only), there is no need for it to be volatile.
如果一个成员变量是只读的,则没有必要设置为volatile
如果一个所有的线程访问这个变量都是在一个同步代码块中,则没有必要设置为volatile
The volatile modifier exists to request that the VM always access the shared copy of the variable. This is less efficient than allowing the VM to perform optimizations by keeping a private copy. You should use volatile only when it is necessary; overuse will unnecessarily slow the application’s execution.
Volatile要求虚拟机的每次对变量的请求都要回访,这对于每个线程保持一个私有拷贝是低效的,会降低访问速度,如非必要,不要使用
synchronized Method Modifier
The addition of the synchronized modifier to a method declaration ensures that only one thread is allowed inside the method at a time. This can be useful in keeping out other threads while the state of an object is temporarily inconsistent.
Synchronized修饰,用来修饰一个方法申明,可以保证同一时间只有一个线程能够调用此方法。
这种机制能够防止对象处于不连续状态时被其他线程访问
Two Threads Simultaneously in the Same Method of One Object
If two or more threads are simultaneously inside a method, each thread has its own copy of local variables.
两个或多个线程同时调用同一对象的相同方法,则每一个线程拥有局部变量的拷贝
One Thread at a Time
More than one thread can be inside a method, and each thread keeps a copy of its own local variables. However, there are times when application constraints require that only one thread be permitted inside a method at a time.
When a thread encounters a synchronized instance method, it blocks until it can get exclusive access to the object-level mutex lock. Mutex is short for mutual exclusion. A mutex lock can be held by only one thread at a time. Other threads waiting for the lock will block until it is released. When the lock is released, all the threads waiting for it compete for exclusive access. Only one will be successful, and the other threads will go back into a blocked state waiting for the lock to be released again.
保证同一时间只有一个线程调用某个方法,只需在方法申明前加上synchronized。当一个线程碰到申明为sychronized的方法实例时,会阻塞,直到它获得对象级互斥锁信号量的访问权,互斥信号在某个时刻只能被一个线程拥有,其他等待此信号的线程必须等候此信号被释放,此互斥锁释放后,其他线程竞争访问权,成功的线程运行,其他的线程继续阻塞等待此互斥锁的再次释放。
Two Threads, Two Objects
Every instance of a class has its own object-level lock.
Although the doStuff() method is synchronized, there is no competition for exclusive access to the object-level lock. Each instance, obj1 and obj2, has its own object-level lock. When threadA enters the doStuff() method of obj1 (line 1), it acquires exclusive access to the object-level lock for obj1. When threadB enters the doStuff() method of obj2 (line 3), it acquires exclusive access to the object-level lock for obj2.
每个对象的实例有自己的对象级锁。换言之,synchronized锁是建立在对象的实例上的,而不是抽象的对象上的。多个线程调用同一个对象实例的同一个synchronized方法时,会同步访问,而多个线程调用同一对象不同实例的同一个synchronized方法时,是不互相互斥访问的。
Avoiding Accidental Corruption of an Object
It’s an unavoidable fact that the object must be in an inconsistent state for a brief period of time, even with everything except the assignments taken out:
public synchronized void setNames(String firstName, String lastName) {
fname = firstName;
lname = lastName;
}
No matter how fast the processor is, it’s possible that the thread scheduler could swap out the thread 易做图 the changes after it has changed fname but before it has changed lname. Holding an object-level lock does not prevent a thread from being swapped out. And if it is swapped out, it continues to hold the object-level lock. Because of this, care must be taken to ensure that all reads are blocked when the data is in an inconsistent state. CleanRead (see Listing 7.16) simply adds the synchronized method modifier to getNames() to control concurrent reading and writing.
两个线程同时调用某实例的方法修改某些变量值,会导致这些变量值在某个时刻状态不连续,加上synchronized修饰此方法,可保证此变量值的完整性
Deferring Access to an Object While It Is Inconsistent
一个线程在调用某个synchornized设置值的方法修改某个实例的某些变量值的时候,只是限制其他线程同时调用此方法,并不限制其他线程调用别的方法访问这些变量值,如果此时另一个线程在调用某个获得值的方法访问这些变量,某些变量可能已经被修改,而另外一些变量还没有修改,有可能造成变量的不连续。
将获得值得方法前加上synchronized修饰符,可解决此问题。因为,一个对象实例只有一个对象级锁,当一个synchronized方法被调用时,此实例的其他synchronized方法必须等待此锁释放。
If two or more threads might be simultaneously interacting with the member variables of an object, and at least one of those threads might change the values, it is generally a good idea to use synchronized to control concurrent access. If only one thread will be accessing an object, using synchronized is unnecessary and slows execution.
synch
上一个:Java Thread Programming 1.8.1 - Inter-thread Communication
下一个:小议学习java的浮躁心态-分析篇