Common thread safety issues and solutions in Java development
In Java development, multi-threading is a very common and important concept. However, multi-threading often brings about a series of thread safety issues. Thread safety issues refer to data errors, logic errors and other issues that may occur when multiple threads access shared resources at the same time. This article will introduce some common thread safety issues and provide corresponding solutions, along with code examples.
Solution 1: Use the synchronized keyword
By using the synchronized keyword on the key code segment, you can ensure that only one thread can execute the code segment at the same time, thereby avoiding race conditions. .
Code example:
class Counter { private int count = 0; public synchronized void increment() { count++; } public int getCount() { return count; } }
Solution 2: Use the Lock interface
Using the Lock interface can provide more fine-grained locking. Compared with synchronized, the Lock interface is more flexible.
Code example:
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class Counter { private int count = 0; private Lock lock = new ReentrantLock(); public void increment() { lock.lock(); try { count++; } finally { lock.unlock(); } } public int getCount() { return count; } }
There are two main ways to prevent deadlock:
The first is to avoid circular dependencies;
The second is to use a thread pool (ThreadPoolExecutor) instead of creating threads individually. The thread pool can effectively manage threads life cycle to prevent deadlock.
Code example:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; class Resource { private final Object lock1 = new Object(); private final Object lock2 = new Object(); public void methodA() { synchronized (lock1) { synchronized (lock2) { // do something } } } public void methodB() { synchronized (lock2) { synchronized (lock1) { // do something } } } } public class Main { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(2); Resource resource = new Resource(); executorService.submit(() -> resource.methodA()); executorService.submit(() -> resource.methodB()); executorService.shutdown(); } }
Solution: Use the wait() and notify() methods together. The wait() method can make the current thread wait, and the notify() method can wake up a waiting thread.
class SharedResource { private int value; private boolean isValueSet = false; public synchronized void setValue(int value) { while (isValueSet) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.value = value; isValueSet = true; notify(); } public synchronized int getValue() { while (!isValueSet) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } isValueSet = false; notify(); return value; } } public class Main { public static void main(String[] args) { SharedResource sharedResource = new SharedResource(); Thread producer = new Thread(() -> { for (int i = 0; i < 10; i++) { sharedResource.setValue(i); System.out.println("Producer produces: " + i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread consumer = new Thread(() -> { for (int i = 0; i < 10; i++) { int value = sharedResource.getValue(); System.out.println("Consumer consumes: " + value); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); producer.start(); consumer.start(); } }
The above is the detailed content of Common thread safety issues and solutions in Java development. For more information, please follow other related articles on the PHP Chinese website!