例子来源: Youtube-cave of programming
When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method’s object and release it when the method returns. - 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.
public class synchronizedDemo { private int count = 0; //make a atomic method, lock the method, only one thread can call it at the same time //same threads will share the method public synchronized void increment() { count++; } public static void main(String[] args) { synchronizedDemo demo = new synchronizedDemo(); demo.doWork(); } public void doWork() { Thread t1 = new Thread(new Runnable(){ @Override public void run() { for(int i=0; i < 10000; i++) { increment(); } } }); Thread t2 = new Thread(new Runnable(){ @Override public void run() { for(int i=0; i < 10000; i++) { increment(); } } }); t1.start(); t2.start(); try { //wait thread to die t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Count:" + count); } }The update to list1 and list2 can happen simultaneously.
import java.util.ArrayList; import java.util.List; import java.util.Random; public class Worker { private Object lock1 = new Object(); private Object lock2 = new Object(); private Random random = new Random(); private List<Integer> list1 = new ArrayList<Integer>(); private List<Integer> list2 = new ArrayList<Integer>(); public void stageOne() { synchronized(lock1){ try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } list1.add(random.nextInt(100)); } } public void stageTwo() { synchronized(lock2){ try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } list2.add(random.nextInt(100)); } } public void process() { for(int i = 0; i < 1000 ; i++) { stageOne(); stageTwo(); } } public void main() { System.out.println("Starting ..."); long start = System.currentTimeMillis(); Thread t1 = new Thread(new Runnable() { @Override public void run() { process(); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { process(); } }); t1.start(); t2.start(); try { t1.join(); t2.join();; } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } long end = System.currentTimeMillis(); System.out.println("Running time: " + (end - start)); System.out.println("length of list1: "+ list1.size()); System.out.println("length of list2: "+ list2.size()); }; }