本文讨论了 Java 中线程同步的重要性以及如何在程序中实现线程同步。
当您的程序有多个线程时,当不同的线程尝试访问相同的资源或同时执行相同的操作时,可能会出现问题。 这种情况会导致错误和并发问题。 让我们以一个示例为例,您的程序中有两个线程试图读取/写入文本文件。 当两个线程都在写入文件时,一个线程的数据可能会被另一个线程覆盖,并且在读取文件时会发现相同的问题。
因此,线程同步是必需的,以便多个线程在任何给定时间点一次访问一个线程。
为什么要使用线程同步?
- 防止线程干扰
- 避免一致性问题和并发问题
- 防止数据丢失
线程同步有互斥和线程间通信两种类型。
- 互斥
- 同步方法。
- 同步块。
- 静态同步。
- 合作(Java 中的线程间通信)
同步块
同步块用于线程同步。
synchronized
关键字用于标识 Java 中的同步块,并基于某些对象进行同步。 其背后的主要概念是,在同一对象上同步的所有同步块一次只能在其中一个线程内执行,这会阻止多个线程同时运行和执行。 尝试进入同步块的所有其他线程将被阻止,直到同步块内的线程退出该块为止。
共享资源保留在此同步块内,以便在给定时间点只有一个线程可以访问特定资源。
同步块的语法如下所示:
synchronized(referencetoobject) {
// Shared variables and other shared resources are placed here
}
监视器
在尝试理解和实现 Java 同步时,监视器的概念很重要。
- Java 中的每个对象都与一个监视器关联
- 线程可以锁定或解锁监视器
- 在给定时间,只有一个线程可以拥有监视器。
- 一次只能有一个线程可以锁定监视器
线程同步示例
//We write a program with a simple counter execution.
class Countings {
public void printing() {
try {
for(int i = 5; i > 0; i--) {
System.out.println( i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
class Threadings extends Thread {
private Thread thrd;
private String thrdName;
Countings gg;
Threadings( String name, Countings abc) {
thrdName = name;
gg = abc;
}
public void run() {
gg.printing();
System.out.println("Thread " + thrdName + " exiting.");
}
public void start () {
System.out.println("Starting " + thrdName );
if (thrd == null) {
thrd = new Thread (this, thrdName);
thrd.start ();
}
}
}
public class Tests {
public static void main(String args[]) {
Countings gg = new Countings();
Countings T1 = new Countings ( "Thread - 1 ", gg );
Countings T2 = new Countings ( "Thread - 2 ", gg );
T1.start();
T2.start();
// threads take some time to end
try {
T1.join();
T2.join();
} catch ( Exception e) {
System.out.println("Interrupted");
}
}
}
输出:(每次运行都会产生不同的结果)
Starting Thread - 1
Starting Thread - 2
5
4
3
5
2
1
4
Thread Thread - 1 exiting.
3
2
1
Thread Thread - 2 exiting.
相同的示例,但是这次具有线程同步:
class Countings {
public void printings() {
try {
for(int i = 5; i > 0; i--) {
System.out.println( i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
class Threadings extends Thread {
private Thread t;
private String thrdName;
Countings gg;
Threadings( String name, Countings abc) {
thrdName = name;
gg = abc;
}
public void run() {
synchronized(gg) {
gg.printings();
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start () {
System.out.println("Starting " + thrdName );
if (thrd == null) {
thrd = new Thread (this, thrdName);
thrd.start ();
}
}
}
public class Testings{
public static void main(String args[]) {
Countings gg = new Countings();
Threadings T1 = new Threadings ( "Thread - 1 ", gg );
Threadings T2 = new Threadings ( "Thread - 2 ", gg );
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
5
4
3
2
1
Thread Thread - 1 exiting.
5
4
3
2
1
Thread Thread - 2 exiting.