📜  同步的局限性和静态同步在多线程中的使用

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

同步的局限性和静态同步在多线程中的使用

Java 的多线程特性是这个概念所围绕的特性,因为它允许并发执行程序的两个或多个部分,以最大限度地利用 CPU。这种程序的每一部分都称为一个线程。因此,线程是进程中的轻量级进程,众所周知,线程可以通过使用列出的两种机制创建:

  1. 扩展 Thread 类
  2. 实现 Runnable 接口

如果多个线程一次访问单个资源,则存在数据竞争或错误输出的可能性。让我们借助一个故事来理解这一点。让我们以多线程中的数据竞速为例,了解同步的局限性和静态同步的用途。让我们直接了解多线程中的数据竞赛。

执行:

Shubham 和 Sharmistha 正在计划约会并试图预订电影票。不幸的是,只有一张票可用。天才Java程序员 Shubham 知道一个技巧,并同时为他们俩同时要求一张票。天真的订票系统分配了 2 个线程并通过 book 方法传递它们。程序结束,两人各拿到一张票,剩下的票数为-1!



插图:多线程中的数据竞赛

Java
// Java program to show Data racing in multithreading.
  
// Helper class 1
class book {
    int tickets = 1;
    // method to book movie ticket
    void book(int request, String name)
    {
        // logic to book ticket
        if (tickets >= request) {
            System.out.println(name + " booked " + request
                               + " ticket.");
            tickets = tickets - 1;
            System.out.println("Tickets left: " + tickets);
        }
        else {
            System.out.println("No tickets are available.");
        }
    }
}
// Helper class 2, extending Thread class.
// book method is called from this class using the object
// passed from main class.
class myThread extends Thread {
    book obj;
    int n;
    String name;
    myThread(book obj, String name, int n)
    {
        this.obj = obj;
        this.n = n;
        this.name = name;
    }
    // runs threads
    public void run() { obj.book(n, name); }
}
// Driver class
public class GFG {
    // Driver method
    public static void main(String[] args)
    {
        // Creating object "obj" of book class and passing
        // it to myThread class
        book obj = new book();
        myThread t1 = new myThread(obj, "Shubham", 1);
        myThread t2 = new myThread(obj, "Sharmistha", 1);
        // When a program calls the start() method, a new
        // thread is created and then the run() method is
        // executed.
  
        // Starting threads created above
        t1.start();
        t2.start();
    }
}


Java
// Java program to handle data racing due to
// multithreading using synchronization.
  
// Helper class 1
class book {
    int tickets = 1;
    // synchronized method to book movie ticket
    synchronized void book(int request, String name)
    {
        // logic to book ticket
        if (tickets >= request) {
            System.out.println(name + " booked " + request
                               + " ticket.");
            tickets = tickets - 1;
            System.out.println("Tickets left: " + tickets);
        }
        else {
            System.out.println("No tickets are available.");
        }
    }
}
// Helper class 2, extending Thread class.
// book method is called from this class using the object
// passed from main class.
class myThread extends Thread {
    book obj;
    int n;
    String name;
    myThread(book obj, String name, int n)
    {
        this.obj = obj;
        this.n = n;
        this.name = name;
    }
    // runs threads
    public void run() { obj.book(n, name); }
}
// Driver class
public class GFG {
    // Driver method
    public static void main(String[] args)
    {
        // Creating object "obj" of book class and passing
        // it to myThread class
        book obj = new book();
        myThread t1 = new myThread(obj, "Shubham", 1);
        myThread t2 = new myThread(obj, "Sharmistha", 1);
        // When a program calls the start() method, a new
        // thread is created and then the run() method is
        // executed.
  
        // Starting threads created above
        t1.start();
        t2.start();
    }
}


Java
// Java program to illustrate limitations of
// synchronization.
  
// Helper class 1
class book {
    int tickets = 1;
    // synchronized method to book movie ticket
    synchronized void book(int request, String name)
    {
        // logic to book ticket
        if (tickets >= request) {
            System.out.println(name + " booked " + request
                               + " ticket.");
            tickets = tickets - 1;
            System.out.println("Tickets left: " + tickets);
        }
        else {
            System.out.println("No tickets are available.");
        }
    }
}
// Helper class 2, extending Thread class.
// book method is called from this class using the object
// passed from main class.
class myThread extends Thread {
    book obj;
    int n;
    String name;
    myThread(book obj, String name, int n)
    {
        this.obj = obj;
        this.n = n;
        this.name = name;
    }
    // runs threads
    public void run() { obj.book(n, name); }
}
// Driver class
public class GFG {
    // Driver method
    public static void main(String[] args)
    {
        // Creating multiple objects "obj" and "obj2" of
        // book class and passing it to myThread class.
        book obj = new book();
        book obj2 = new book();
        myThread t1 = new myThread(obj, "Shubham", 1);
        myThread t2 = new myThread(obj2, "Sharmistha", 1);
        // When a program calls the start() method, a new
        // thread is created and then the run() method is
        // executed.
  
        // Starting threads created above
        t1.start();
        t2.start();
    }
}


Java
// Java program to handle data racing using static
// synchronization.
  
// Helper class 1
class book {
    static int tickets = 1;
    // static synchronized method to book movie ticket
    static synchronized void book(int request, String name)
    {
        // logic to book ticket
        if (tickets >= request) {
            System.out.println(name + " booked " + request
                               + " ticket.");
            tickets = tickets - 1;
            System.out.println("Tickets left: " + tickets);
        }
        else {
            System.out.println(
                name + ", No tickets are available.");
        }
    }
}
// Helper class 2, extending Thread class.
// book method is called from this class using the object
// passed from main class.
class myThread extends Thread {
    book obj;
    int n;
    String name;
    myThread(book obj, String name, int n)
    {
        this.obj = obj;
        this.n = n;
        this.name = name;
    }
    // runs Threads
    public void run() { obj.book(n, name); }
}
// Driver class
public class GFG {
    // Driver method
    public static void main(String[] args)
    {
        // Creating object "obj" of book class and passing
        // it to myThread class
        book obj = new book();
        book obj2 = new book();
        myThread t1 = new myThread(obj, "Shubham", 1);
        myThread t2 = new myThread(obj2, "Sharmistha", 1);
        // When a program calls the start() method, a new
        // thread is created and then the run() method is
        // executed.
  
        // Starting threads created above
        t1.start();
        t2.start();
    }
}


输出-

Shubham booked 1 ticket.
Sharmistha booked 1 ticket.
Tickets left: 0
Tickets left: -1

票数不能为负数。为了解决这个问题,工程师提出了同步概念。

同步——我们为对象提供一个锁并声明一个敏感区域(withdraw 方法)。一个对象可以有多个线程,但敏感区域一次只能被 1 个线程访问。

插图:使用同步处理由于多线程导致的数据竞争。

Java

// Java program to handle data racing due to
// multithreading using synchronization.
  
// Helper class 1
class book {
    int tickets = 1;
    // synchronized method to book movie ticket
    synchronized void book(int request, String name)
    {
        // logic to book ticket
        if (tickets >= request) {
            System.out.println(name + " booked " + request
                               + " ticket.");
            tickets = tickets - 1;
            System.out.println("Tickets left: " + tickets);
        }
        else {
            System.out.println("No tickets are available.");
        }
    }
}
// Helper class 2, extending Thread class.
// book method is called from this class using the object
// passed from main class.
class myThread extends Thread {
    book obj;
    int n;
    String name;
    myThread(book obj, String name, int n)
    {
        this.obj = obj;
        this.n = n;
        this.name = name;
    }
    // runs threads
    public void run() { obj.book(n, name); }
}
// Driver class
public class GFG {
    // Driver method
    public static void main(String[] args)
    {
        // Creating object "obj" of book class and passing
        // it to myThread class
        book obj = new book();
        myThread t1 = new myThread(obj, "Shubham", 1);
        myThread t2 = new myThread(obj, "Sharmistha", 1);
        // When a program calls the start() method, a new
        // thread is created and then the run() method is
        // executed.
  
        // Starting threads created above
        t1.start();
        t2.start();
    }
}

输出-

Shubham booked 1 ticket.
Tickets left: 0
No tickets are available.

同步的限制:

如果 我们有来自 1 个对象的多个线程,而不是同步将处理数据竞争或错误输出。如果从多个对象分配多个线程会发生什么?这将再次导致不良输出或数据竞争。



插图:从多个对象分配多个线程时同步的缺点。

Java

// Java program to illustrate limitations of
// synchronization.
  
// Helper class 1
class book {
    int tickets = 1;
    // synchronized method to book movie ticket
    synchronized void book(int request, String name)
    {
        // logic to book ticket
        if (tickets >= request) {
            System.out.println(name + " booked " + request
                               + " ticket.");
            tickets = tickets - 1;
            System.out.println("Tickets left: " + tickets);
        }
        else {
            System.out.println("No tickets are available.");
        }
    }
}
// Helper class 2, extending Thread class.
// book method is called from this class using the object
// passed from main class.
class myThread extends Thread {
    book obj;
    int n;
    String name;
    myThread(book obj, String name, int n)
    {
        this.obj = obj;
        this.n = n;
        this.name = name;
    }
    // runs threads
    public void run() { obj.book(n, name); }
}
// Driver class
public class GFG {
    // Driver method
    public static void main(String[] args)
    {
        // Creating multiple objects "obj" and "obj2" of
        // book class and passing it to myThread class.
        book obj = new book();
        book obj2 = new book();
        myThread t1 = new myThread(obj, "Shubham", 1);
        myThread t2 = new myThread(obj2, "Sharmistha", 1);
        // When a program calls the start() method, a new
        // thread is created and then the run() method is
        // executed.
  
        // Starting threads created above
        t1.start();
        t2.start();
    }
}

输出-

Shubham booked 1 ticket.
Tickets left: 0
Sharmistha booked 1 ticket.
Tickets left: 0

我们只有一张票,但由于数据竞争,他们都成功预订了!为了解决这个问题,我们需要研究静态同步。

静态同步 -假设我们有 5 个对象。每个对象都有多个线程。现在敏感区域将一次被 5 个线程访问!

为了解决这个问题,工程师提出了静态同步的想法。我们为班级提供了一个锁。该类将一次选择 1 个对象。物体将依次选择 1 个线程并通过敏感区域。

插图:使用静态同步处理数据竞赛。

Java

// Java program to handle data racing using static
// synchronization.
  
// Helper class 1
class book {
    static int tickets = 1;
    // static synchronized method to book movie ticket
    static synchronized void book(int request, String name)
    {
        // logic to book ticket
        if (tickets >= request) {
            System.out.println(name + " booked " + request
                               + " ticket.");
            tickets = tickets - 1;
            System.out.println("Tickets left: " + tickets);
        }
        else {
            System.out.println(
                name + ", No tickets are available.");
        }
    }
}
// Helper class 2, extending Thread class.
// book method is called from this class using the object
// passed from main class.
class myThread extends Thread {
    book obj;
    int n;
    String name;
    myThread(book obj, String name, int n)
    {
        this.obj = obj;
        this.n = n;
        this.name = name;
    }
    // runs Threads
    public void run() { obj.book(n, name); }
}
// Driver class
public class GFG {
    // Driver method
    public static void main(String[] args)
    {
        // Creating object "obj" of book class and passing
        // it to myThread class
        book obj = new book();
        book obj2 = new book();
        myThread t1 = new myThread(obj, "Shubham", 1);
        myThread t2 = new myThread(obj2, "Sharmistha", 1);
        // When a program calls the start() method, a new
        // thread is created and then the run() method is
        // executed.
  
        // Starting threads created above
        t1.start();
        t2.start();
    }
}

输出-

Shubham booked 1 ticket.
Tickets left: 0
Sharmistha, No tickets are available.

使用静态同步,我们准备了一个防止非法订票的系统。

结论-