📜  Java中线程同步的重要性

📅  最后修改于: 2022-05-13 01:55:24.812000             🧑  作者: Mango

Java中线程同步的重要性

我们的系统在多线程环境中工作,这成为操作系统提供更好的资源利用率的重要组成部分。同时运行程序的两个或多个部分的过程称为多线程。程序是一组指令,其中多个进程正在运行,并且在一个进程内,多个线程正在工作。线程只不过是轻量级进程。例如,在计算机中,我们在玩电子游戏的同时使用 MS word 和听音乐。所以,这些是我们同时处理的流程。在这种情况下,每个应用程序都有多个子进程,即线程。在前面的例子中,我们听音乐,我们有一个音乐播放器作为一个应用程序,其中包含多个运行的子进程,如管理播放列表、访问互联网等。因此,线程是要执行的任务和多线程是在同一个程序中同时执行多个任务/进程。

这是多线程的基本介绍,将进一步帮助理解线程同步的重要性。

线程优先级

在Java,每个线程都被分配了一个优先级,该优先级决定了线程应该如何相互对待。线程的优先级用于决定何时从一个正在运行的线程切换到下一个。较高优先级的线程可以抢占较低优先级的线程,并可能占用更多的 CPU 时间。简单来说,与优先级较低的线程相比,优先级较高的线程首先获得资源。但是,如果具有相同优先级的两个线程想要相同的资源,则情况会变得更加复杂。因此,在多线程环境中,如果具有相同优先级的线程使用相同的资源,则会产生不需要的结果或错误的代码。

让我们举个例子。在一个房间里,我们有多台计算机连接到一台打印机。有一次,一台计算机想要打印一份文档,所以它使用了打印机。同时,另一台计算机希望打印机打印其文档。因此,两台计算机需要相同的资源,即打印机。因此,如果两个进程一起运行,那么打印机将打印一台计算机和另一台计算机的文档。这将产生无效的输出。现在,如果两个线程具有相同的优先级或想要相同的资源导致不一致的输出,那么在线程的情况下会发生同样的事情。



在Java,当两个或多个线程尝试同时访问同一资源时,它会导致Java运行时缓慢执行一个或多个线程,甚至暂停它们的执行。为了克服这个问题,我们有线程同步。

同步 意味着多个进程/线程之间的协调。

同步类型:

有两种类型的同步,如下所示:

  1. 进程同步
  2. 线程同步

在这里,我们将主要关注线程同步。

线程同步基本上是指 一个线程一次执行的概念,其余线程处于等待状态。这个过程称为线程同步。它可以防止线程干扰和不一致问题。

同步是使用锁或监视器构建的。在Java,监视器是用作互斥锁的对象。一次只有一个线程有权拥有监视器。当一个线程获得锁时,所有其他试图获取锁定监视器的线程都将被挂起。因此,据说其他线程正在等待监视器,直到第一个线程退出监视器。简单来说,当一个线程请求一个资源时,该资源就会被锁定,这样在资源被释放之前,其他线程都不能工作或进行任何修改。

线程同步有两种类型:



  1. 互斥
  2. 线程间通信

A.互斥

在共享任何资源时,这将使线程相互干扰,即互斥。我们可以通过

  • 同步方法
  • 同步块
  • 静态同步

同步方法

我们可以声明一个方法为同步使用 “同步”的 关键词。这将使编写在方法中的代码成为线程安全的,以便在共享资源时不会执行其他线程。

执行:

我们将提议同时打印两个线程,显示没有线程同步的异步行为。

示例 1:

Java
// Class 1
// Helper class
// Extending Thread class
public class PrintTest extends Thread {
 
    // Non synchronized Code
 
    // Method 1
    public void printThread(int n)
    {
 
        // This loop will print the  currently executed
        // thread
        for (int i = 1; i <= 10; i++) {
            System.out.println("Thread " + n
                               + " is working...");
 
            // Try block to check for exceptions
            try {
 
                // Pause the execution of current thread
                // for 0.600 seconds using sleep() method
                Thread.sleep(600);
            }
 
            // Catch block to handle the exceptions
            catch (Exception ex) {
 
                // Overriding existing toString() method and
                // prints exception if occur
                System.out.println(ex.toString());
            }
        }
 
        // Display message for better readability
        System.out.println("--------------------------");
 
        try {
 
            // Pause the execution of current  thread
            // for 0.1000 millisecond or 1sec using sleep
            // method
            Thread.sleep(1000);
        }
 
        catch (Exception ex) {
 
            // Printing the exception
            System.out.println(ex.toString());
        }
    }
}
 
// Class 2
// Helper class extending Thread Class
public class Thread1 extends Thread {
 
    // Declaring variable of type Class1
    PrintTest test;
 
    // Constructor for class1
    Thread1(PrintTest p) { test = p; }
 
    // run() method of this class for
    // entry point for thread1
    public void run()
    {
 
        // Calling method  1 as in above class
        test.printThread(1);
    }
}
 
// Class 3
// Helper class extending Thread Class
public class Thread2 extends Thread {
 
    // Declaring variable of type Class1
    PrintTest test;
 
    // Constructor for class2
    Thread2(PrintTest p) { test = p; }
 
    // run() method of this class for
    // entry point for thread2
    public void run() { test.printThread(2); }
}
 
// Class 4
// Main class
public class SynchroTest {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating object of class 1 inside main() method
        PrintTest p = new PrintTest();
 
        // Passing the same object of class PrintTest to
        // both threads
        Thread1 t1 = new Thread1(p);
        Thread2 t2 = new Thread2(p);
 
        // Start executing the threads
        // using start() method
        t1.start();
        t2.start();
 
        // This will print both the threads simuntaneously
    }
}


Java
// Java Program Illustrating Lock the Object for
// the shared resource giving consistent output
 
// Class 1
// Helper class extending Thread class
public class PrintTest extends Thread {
 
    // synchronized code
    // synchronized method will lock the object and
    // releases when thread is terminated or completed its
    // execution.
    synchronized public void printThread(int n)
    {
        for (int i = 1; i <= 10; i++) {
            System.out.println("Thread " + n
                               + " is working...");
 
            try {
 
                // pause the execution of current  thread
                // for 600 millisecond
                Thread.sleep(600);
            }
            catch (Exception ex) {
                // overrides toString() method  and prints
                // exception if occur
                System.out.println(ex.toString());
            }
        }
        System.out.println("--------------------------");
        try {
 
            // pause the execution of current  thread for
            // 1000 millisecond
            Thread.sleep(1000);
        }
        catch (Exception ex) {
            System.out.println(ex.toString());
        }
    }
}
// creating thread1 extending Thread Class
 
public class Thread1 extends Thread {
 
    PrintTest test;
    Thread1(PrintTest p) { test = p; }
 
    public void run() // entry point for thread1
    {
 
        test.printThread(1);
    }
}
// creating thread2 extending Thread Class
 
public class Thread2 extends Thread {
 
    PrintTest test;
    Thread2(PrintTest p) { test = p; }
    public void run() // entry point for thread2
    {
        test.printThread(2);
    }
}
 
public class SynchroTest {
 
    public static void main(String[] args)
    {
 
        PrintTest p = new PrintTest();
       
        // passing the same object of class PrintTest to
        // both threads
        Thread1 t1 = new Thread1(p);
        Thread2 t2 = new Thread2(p);
       
        // start function will execute the threads
        t1.start();
        t2.start();
    }
}


Java
// Java Program Illustrating  Synchronized Code
// Using synchronized block
 
// Class 1
// Helper class extending Thread class
class PrintTest extends Thread {
 
    // Method  1
    // To print the thread
    public void printThread(int n)
    {
 
        // Making synchronized block that makes the block
        // synchronized
        synchronized (this)
        {
 
            // Iterating using for loop
            for (int i = 1; i <= 10; i++) {
 
                // Print message when these thread are
                // executing
                System.out.println("Thread " + n
                                   + " is working...");
 
                // Try block to check for exceptions
                try {
 
                    // Making thread to pause for 0.6
                    // seconds
                    Thread.sleep(600);
                }
 
                // Catch block to handle exceptions
                catch (Exception ex) {
 
                    // Print message when exception.s occur
                    System.out.println(ex.toString());
                }
            }
        }
 
        // Display message only
        System.out.println("--------------------------");
 
        try {
 
            // Making thread t osleep for 1 sec
            Thread.sleep(1000);
        }
 
        catch (Exception ex) {
 
            System.out.println(ex.toString());
        }
    }
}
 
// Class 2
// Helper class extending Thread class
class Thread1 extends Thread {
 
    PrintTest test;
    Thread1(PrintTest p) { test = p; }
 
    public void run() { test.printThread(1); }
}
 
// Class 3
// Helper class extending Thread class
class Thread2 extends Thread {
 
    PrintTest test;
    Thread2(PrintTest p) { test = p; }
 
    public void run() { test.printThread(2); }
}
 
// Class 4
// Main class
class SynchroTest {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating instance for class 1 inside main()
        PrintTest p = new PrintTest();
 
        // Creating threads and
        // passing same object
        Thread1 t1 = new Thread1(p);
        Thread2 t2 = new Thread2(p);
 
        // Starting these thread using start() method
        t1.start();
        t2.start();
    }
}


Java
// Java Program Illustrate  Synchronized
// Using static synchronization
 
// Class 1
// Helper class
class PrintTest extends Thread {
 
    // Static synchronization locks the class PrintTest
    synchronized public static void printThread(int n)
    {
 
        for (int i = 1; i <= 10; i++) {
 
            // Print message when threads are executing
            System.out.println("Thread " + n
                               + " is working...");
 
            // Try block to check for exceptions
            try {
 
                // making thread to sleep for 0.6 seconds
                Thread.sleep(600);
            }
 
            // Catch block to handle the exceptions
            catch (Exception ex) {
 
                // Print message when exception occurs
                System.out.println(ex.toString());
            }
        }
 
        // Display message for better readobility
        System.out.println("--------------------------");
 
        try {
            Thread.sleep(1000);
        }
 
        catch (Exception ex) {
            System.out.println(ex.toString());
        }
    }
}
 
// Class 2
// Helper class extending Thread class
class Thread1 extends Thread {
 
    // run() method for thread
    public void run()
    {
 
        // Passing the class not the object
        PrintTest.printThread(1);
    }
}
 
// Class 3
// Helper class extending Thread class
class Thread2 extends Thread {
 
    public void run()
    {
 
        // Passing the class not the object
        PrintTest.printThread(2);
    }
}
 
// Class 4
// Main class
class SynchroTest {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // No shared object
        // Creating objects of ckass 2 and 3 that
        // are extending to Thr3ead class
        Thread1 t1 = new Thread1();
        Thread2 t2 = new Thread2();
 
        // Starting thread with help of start() method
        t1.start();
        t2.start();
    }
}


输出:

示例 2:

Java

// Java Program Illustrating Lock the Object for
// the shared resource giving consistent output
 
// Class 1
// Helper class extending Thread class
public class PrintTest extends Thread {
 
    // synchronized code
    // synchronized method will lock the object and
    // releases when thread is terminated or completed its
    // execution.
    synchronized public void printThread(int n)
    {
        for (int i = 1; i <= 10; i++) {
            System.out.println("Thread " + n
                               + " is working...");
 
            try {
 
                // pause the execution of current  thread
                // for 600 millisecond
                Thread.sleep(600);
            }
            catch (Exception ex) {
                // overrides toString() method  and prints
                // exception if occur
                System.out.println(ex.toString());
            }
        }
        System.out.println("--------------------------");
        try {
 
            // pause the execution of current  thread for
            // 1000 millisecond
            Thread.sleep(1000);
        }
        catch (Exception ex) {
            System.out.println(ex.toString());
        }
    }
}
// creating thread1 extending Thread Class
 
public class Thread1 extends Thread {
 
    PrintTest test;
    Thread1(PrintTest p) { test = p; }
 
    public void run() // entry point for thread1
    {
 
        test.printThread(1);
    }
}
// creating thread2 extending Thread Class
 
public class Thread2 extends Thread {
 
    PrintTest test;
    Thread2(PrintTest p) { test = p; }
    public void run() // entry point for thread2
    {
        test.printThread(2);
    }
}
 
public class SynchroTest {
 
    public static void main(String[] args)
    {
 
        PrintTest p = new PrintTest();
       
        // passing the same object of class PrintTest to
        // both threads
        Thread1 t1 = new Thread1(p);
        Thread2 t2 = new Thread2(p);
       
        // start function will execute the threads
        t1.start();
        t2.start();
    }
}

输出:

B. 同步区块

如果我们将一个块声明为同步的,那么只有写在该块内的代码会被顺序执行,而不是完整的代码。当我们想要对代码的某些部分进行顺序访问或同步代码的某些部分时,可以使用它。

句法:

synchronized (object reference) 
{    
   // Insert code here
}

例子

Java

// Java Program Illustrating  Synchronized Code
// Using synchronized block
 
// Class 1
// Helper class extending Thread class
class PrintTest extends Thread {
 
    // Method  1
    // To print the thread
    public void printThread(int n)
    {
 
        // Making synchronized block that makes the block
        // synchronized
        synchronized (this)
        {
 
            // Iterating using for loop
            for (int i = 1; i <= 10; i++) {
 
                // Print message when these thread are
                // executing
                System.out.println("Thread " + n
                                   + " is working...");
 
                // Try block to check for exceptions
                try {
 
                    // Making thread to pause for 0.6
                    // seconds
                    Thread.sleep(600);
                }
 
                // Catch block to handle exceptions
                catch (Exception ex) {
 
                    // Print message when exception.s occur
                    System.out.println(ex.toString());
                }
            }
        }
 
        // Display message only
        System.out.println("--------------------------");
 
        try {
 
            // Making thread t osleep for 1 sec
            Thread.sleep(1000);
        }
 
        catch (Exception ex) {
 
            System.out.println(ex.toString());
        }
    }
}
 
// Class 2
// Helper class extending Thread class
class Thread1 extends Thread {
 
    PrintTest test;
    Thread1(PrintTest p) { test = p; }
 
    public void run() { test.printThread(1); }
}
 
// Class 3
// Helper class extending Thread class
class Thread2 extends Thread {
 
    PrintTest test;
    Thread2(PrintTest p) { test = p; }
 
    public void run() { test.printThread(2); }
}
 
// Class 4
// Main class
class SynchroTest {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating instance for class 1 inside main()
        PrintTest p = new PrintTest();
 
        // Creating threads and
        // passing same object
        Thread1 t1 = new Thread1(p);
        Thread2 t2 = new Thread2(p);
 
        // Starting these thread using start() method
        t1.start();
        t2.start();
    }
}

输出:

C. 静态同步

在这种情况下,同步方法被声明为“静态” ,这意味着锁或监视器应用于类而不是对象,因此一次只有一个线程将访问该类。

例子

Java

// Java Program Illustrate  Synchronized
// Using static synchronization
 
// Class 1
// Helper class
class PrintTest extends Thread {
 
    // Static synchronization locks the class PrintTest
    synchronized public static void printThread(int n)
    {
 
        for (int i = 1; i <= 10; i++) {
 
            // Print message when threads are executing
            System.out.println("Thread " + n
                               + " is working...");
 
            // Try block to check for exceptions
            try {
 
                // making thread to sleep for 0.6 seconds
                Thread.sleep(600);
            }
 
            // Catch block to handle the exceptions
            catch (Exception ex) {
 
                // Print message when exception occurs
                System.out.println(ex.toString());
            }
        }
 
        // Display message for better readobility
        System.out.println("--------------------------");
 
        try {
            Thread.sleep(1000);
        }
 
        catch (Exception ex) {
            System.out.println(ex.toString());
        }
    }
}
 
// Class 2
// Helper class extending Thread class
class Thread1 extends Thread {
 
    // run() method for thread
    public void run()
    {
 
        // Passing the class not the object
        PrintTest.printThread(1);
    }
}
 
// Class 3
// Helper class extending Thread class
class Thread2 extends Thread {
 
    public void run()
    {
 
        // Passing the class not the object
        PrintTest.printThread(2);
    }
}
 
// Class 4
// Main class
class SynchroTest {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // No shared object
        // Creating objects of ckass 2 and 3 that
        // are extending to Thr3ead class
        Thread1 t1 = new Thread1();
        Thread2 t2 = new Thread2();
 
        // Starting thread with help of start() method
        t1.start();
        t2.start();
    }
}

输出: