Java thread synchronization is fundamentally in line with a logic: add lock------->modify-------->release lock
1. Synchronize code blocks
Examples are as follows:
public class SyncBlock { static class DataWrap { int i; } static class SyncBlockThread extends Thread { private DataWrap date; public SyncBlockThread(DataWrap dataWrap) { this.date = dataWrap; } @Override public void run() { for (int i = 0; i < 10; i++) { synchronized (date) { date.i++; try { sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getName() + " " + date.i); } } } } public static void main(String[] args) { //Multi-thread implementation variable i adds one output in sequence DataWrap dataWrap = new DataWrap(); new SyncBlockThread(dataWrap).start(); new SyncBlockThread(dataWrap).start(); new SyncBlockThread(dataWrap).start(); }}In the example, you want to output integers in sequence.
Usually, synchronous code blocks are objects that need to be locked, and are generally shared resources that require concurrent access. Any thread first locks the resource before modifying the specified resource. During the locking period, other threads cannot modify the resource. This ensures the security of threads. In addition, the thread will not give up the resource lock when calling sleep or yield.
2. Synchronization method
public class SyncMethod { static class DataWrap{ int i; public synchronized void valueGrow(){ i++; try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " " + i); } } static class SyncMethodThread extends Thread { DataWrap dataWrap; public SyncMethodThread(DataWrap dataWrap){ this.dataWrap = dataWrap; } @Override public void run() { for (int i = 0; i < 10; i++) { dataWrap.valueGrow(); } } } public static void main(String[] args) { //Implement sequential growth and output i DataWrap dataWrap = new DataWrap(); new SyncMethodThread(dataWrap).start(); new SyncMethodThread(dataWrap).start(); new SyncMethodThread(dataWrap).start(); }}The synchronization method is a method modified by the synchronized keyword. The synchronization method locks the object itself. Therefore, when a thread calls the synchronization method of a certain object, if other threads call other synchronization methods of the object, they still have to wait to release the lock of the object because the object has been locked.
3. Synchronous lock
Synchronization is achieved by defining a synchronization lock object, in which case the synchronization lock uses a Lock object to act as.
import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class SyncLock { static class DataWrap{ Lock lock = new ReentrantLock(); int i; public void valueGrow(){ lock.lock(); try { i++; try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " " + i); } finally { lock.unlock(); } } } static class SyncLockThread extends Thread { DataWrap dataWrap; public SyncLockThread(DataWrap dataWrap){ this.dataWrap = dataWrap; } @Override public void run() { for (int i = 0; i < 10; i++) { dataWrap.valueGrow(); } } } public static void main(String[] args) { //Implement sequential growth and output i DataWrap dataWrap = new DataWrap(); new SyncLockThread(dataWrap).start(); new SyncLockThread(dataWrap).start(); new SyncLockThread(dataWrap).start(); }}Using lock objects to implement thread synchronization will be more flexible. Some locks also have some specific functions, among which the more commonly used ReadWriteLock read and write locks, and ReentrantLock can reenter the lock.