天天看点

Effective Java 66 Synchronize access to shared mutable data

synchronized - only a single thread can execute a method or

block at one time.  

not only does synchronization prevent a thread from observing

an object in an inconsistent state, but it ensures that each thread entering a

synchronized method or block sees the effects of all previous modifications that

were guarded by the same lock. 

synchronization is required for reliable communication between

threads as well as for mutual exclusion. 

principles 

do not use thread.stop. 

synchronization has no effect unless both read and write

operations are synchronized. 

/** 

 * demo for 66 synchronize access to shared mutable

data. 

 */ 

package com.effectivejava.concurrency; 

import

java.util.concurrent.timeunit; 

 * properly

synchronized cooperative thread termination 

 * @author kaibo 

 *  

public

class stopthread { 

private

static boolean stoprequested;

private static synchronized void requeststop() { 

stoprequested =

true; 

system.out.println("request

stop from another thread."); 

}  

static synchronized boolean stoprequested()

return stoprequested; 

static void main(string[] args)

throws interruptedexception { 

thread backgroundthread =

new thread(new runnable() { 

public void

run() { 

int i = 0; 

while

(!stoprequested()) 

system.out.println(i++); 

}); 

backgroundthread.start(); 

timeunit.seconds.sleep(1); 

requeststop(); 

 * cooperative thread termination with a volatile

field 

class stopthreadwithvolatile { 

private static volatile boolean stoprequested; 

public static void

main(string[] args)

(!stoprequested) 

stoprequested = true; 

note  

operator(++) is not atomic - if a second thread reads the field

between the time a thread reads the old value and writes back a new one, the

second thread will see the same value as the first and return the same serial

number. 

// broken - requires synchronization! 

private static volatile int nextserialnumber = 0; 

static int generateserialnumber() { 

return nextserialnumber++; 

// correct way 

private static final atomic long nextserialnum =

new atomiclong(); 

public static

long generateserialnumber()

return

nextserialnum.getandincrement(); 

4. confine mutable data to a single thread  

summary 

when multiple threads

share mutable data, each thread that reads or writes the data must perform

synchronization. without synchronization, there is no guarantee that one

thread’s changes will be visible to another. the penalties for failing to

synchronize shared mutable data are liveness and safety failures. if you

need only

inter-thread communication,

and not mutual exclusion, the volatile modifier is an acceptable form of

synchronization, but it can be tricky to use correctly.