Java 简明教程
Java - Thread Synchronization
Need of Thread Synchronization?
当我们在程序中启动 two or more threads 时,可能会出现多个线程尝试访问同一资源的情况,最终它们可能会因并发问题而产生 unforeseen 结果。例如,如果多个线程尝试写入同一文件,则它们可能会损坏数据,因为其中一个线程可以覆盖数据或在其中一个线程打开同一文件的同时,另一个线程可能会关闭同一文件。
因此,需要同步多个线程的动作并确保仅有一个线程可以在给定的时间点访问该资源。这是通过一个称为 monitors 的概念来实现的。Java 中的每个对象都与一个监视器关联,线程可以锁定或解锁该监视器。一次只能有一个线程持有对一个监视器的锁定。
Thread Synchronization in Java
Java 编程语言提供了一种使用 synchronized 块创建线程并同步它们的 task 的非常便捷的方式。你将共享的资源保留在此块内。以下是同步语句的一般形式−
Multithreading Example without Thread Synchronization
这是一个简单的示例,它可能并不会按顺序打印 counter 的值,而且每次运行都会基于线程对 CPU 的可用性产生不同的结果。
Example
class PrintDemo {
public void printCount() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd) {
threadName = name;
PD = pd;
}
public void run() {
PD.printCount();
System.out.println("Thread " + threadName + " exiting.");
}
public void start () {
System.out.println("Starting " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
public class TestThread {
public static void main(String args[]) {
PrintDemo PD = new PrintDemo();
ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD );
ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD );
T1.start();
T2.start();
// wait for threads to end
try {
T1.join();
T2.join();
} catch ( Exception e) {
System.out.println("Interrupted");
}
}
}
每次运行该程序都会产生不同的结果——
Starting Thread - 1
Starting Thread - 2
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 5
Counter --- 2
Counter --- 1
Counter --- 4
Thread Thread - 1 exiting.
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 2 exiting.
Multithreading Example with Thread Synchronization
这里有一个在序列中打印 counter 值的相同示例,我们每次运行它时,它都会产生相同的结果。
Example
class PrintDemo {
public void printCount() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd) {
threadName = name;
PD = pd;
}
public void run() {
synchronized(PD) {
PD.printCount();
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start () {
System.out.println("Starting " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
public class TestThread {
public static void main(String args[]) {
PrintDemo PD = new PrintDemo();
ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD );
ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD );
T1.start();
T2.start();
// wait for threads to end
try {
T1.join();
T2.join();
} catch ( Exception e) {
System.out.println("Interrupted");
}
}
}
每次运行此程序都会产生相同的结果 −
Starting Thread - 1
Starting Thread - 2
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 1 exiting.
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 2 exiting.