由于多个线程对共享资源的并发访问,可能导致程序出现不确定的结果或发生异常的情况。线程安全问题主要包括以下几个方面:
-
竞态条件(Race Condition): 多个线程同时对共享资源进行读写操作,由于执行顺序不确定,可能导致结果出现错误。例如,在没有适当同步的情况下,多个线程同时对某个计数器进行自增操作。
-
数据不一致(Inconsistent Data): 一个线程正在修改共享资源的数据,而另一个线程同时读取该数据,可能读取到的是被修改过一半的数据。这通常发生在没有同步机制的情况下。
-
解决方法:同步代码块
-
同步代码块是一种通过使用
synchronized
关键字来实现线程同步的机制。可以使用同步代码块来保证多个线程对共享资源的安全访问。 -
synchronized (monitorObject) { // 在这里执行需要同步的代码 } public class SynchronizedExample { private int count = 0; private Object lock = new Object(); public void increment() { synchronized (lock) { //synchronized必须在循环里面,锁对象一定要是唯一。 count++; System.out.println(Thread.currentThread().getName() + " - Incremented: " + count); } } public static void main(String[] args) { SynchronizedExample example = new SynchronizedExample(); // 创建两个线程,同时调用 increment 方法 Thread thread1 = new Thread(() -> { for (int i = 0; i < 5; i++) { example.increment(); } }); Thread thread2 = new Thread(() -> { for (int i = 0; i < 5; i++) { example.increment(); } }); // 启动两个线程 thread1.start(); thread2.start(); } }
同步方法是一种简化的同步机制,它使用
synchronized
关键字修饰方法,确保在任一时刻只有一个线程可以进入该方法,防止多个线程同时执行该方法导致的线程安全问题。 -
锁住方法里面所有代码,锁对象不能自己指定
public synchronized void methodName() {
// 方法体
}
public class SynchronizedMethodExample {
private int count = 0;
// 同步方法
public synchronized void increment() {
count++;
System.out.println(Thread.currentThread().getName() + " - Incremented: " + count);
}
public static void main(String[] args) {
SynchronizedMethodExample example = new SynchronizedMethodExample();
// 创建两个线程,同时调用 increment 方法
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
example.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
example.increment();
}
});
// 启动两个线程
thread1.start();
thread2.start();
}
}