Java多线程的临界资源问题

Posted ggrrbb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程的临界资源问题相关的知识,希望对你有一定的参考价值。

临界资源问题的原因:某一个线程在对临界资源进行访问时,还没来得及完全修改临界资源的值,临界资源就被其他线程拿去访问,导致多个线程访问同一资源。直观表现为打印结果顺序混乱。

解决方法:加锁

静态方法中用类锁,非静态方法中用对象锁。

1.同步代码段:synchronized(){...}
2.同步方法:使用关键字synchronized修饰的方法
3.使用显式同步锁ReentrantLock

锁池描述的即为锁外等待的状态

方法一:同步代码段:synchronized(){...}

public class SourceConflict {
    public static void main(String[] args) {
        //实例化4个售票员,用4个线程模拟4个售票员
        
        Runnable r = () -> {
            while (TicketCenter.restCount > 0) {
                synchronized(" ") {
                    if (TicketCenter.restCount <= 0) {
                        return;
                    }
                    System.out.println(Thread.currentThread().getName() + "卖出一张票,剩余" + --TicketCenter.restCount + "张票");
                }
            }
        };
        
        //用4个线程模拟4个售票员
        Thread thread1 = new Thread(r, "thread-1");
        Thread thread2 = new Thread(r, "thread-2");
        Thread thread3 = new Thread(r, "thread-3");
        Thread thread4 = new Thread(r, "thread-4");
        
        //开启线程
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
        
    }    
}

//实现四名售票员共同售票,资源共享,非独立
//Lambda表达式或匿名内部类内部捕获的局部变量必须显式的声明为 final 或实际效果的的 final 类型,而捕获实例或静态变量是没有限制的
class TicketCenter{
    public static int restCount = 100; 
}

方法二:同步方法,即使用关键字synchronized修饰的方法

 1 public class SourceConflict2 {
 2     public static void main(String[] args) {
 3         //实例化4个售票员,用4个线程模拟4个售票员
 4         
 5         Runnable r = () -> {
 6             while (TicketCenter.restCount > 0) {
 7                 sellTicket();
 8             }
 9         };
10         
11         //用4个线程模拟4个售票员
12         Thread thread1 = new Thread(r, "thread-1");
13         Thread thread2 = new Thread(r, "thread-2");
14         Thread thread3 = new Thread(r, "thread-3");
15         Thread thread4 = new Thread(r, "thread-4");
16         
17         //开启线程
18         thread1.start();
19         thread2.start();
20         thread3.start();
21         thread4.start();
22         
23     }
24     
25     private synchronized static void sellTicket() {    
26         if (TicketCenter.restCount <= 0) {
27             return;
28         }
29         System.out.println(Thread.currentThread().getName() + "卖出一张票,剩余" + --TicketCenter.restCount + "张票");
30     }
31 }
32 
33 class TicketCenter{
34     public static int restCount = 100; 
35 }

方法三:使用显式同步锁ReentrantLock

 1 import java.util.concurrent.locks.ReentrantLock;
 2 
 3 public class SourceConflict3 {
 4     public static void main(String[] args) {
 5         //实例化4个售票员,用4个线程模拟4个售票员
 6         
 7         //显式锁
 8         ReentrantLock lock = new ReentrantLock();
 9         Runnable r = () -> {
10             while (TicketCenter.restCount > 0) {
11                 lock.lock();
12                 if (TicketCenter.restCount <= 0) {
13                     return;
14                 }
15                 System.out.println(Thread.currentThread().getName() + "卖出一张票,剩余" + --TicketCenter.restCount + "张票");
16                 lock.unlock();
17             }
18         };
19         
20         //用4个线程模拟4个售票员
21         Thread thread1 = new Thread(r, "thread-1");
22         Thread thread2 = new Thread(r, "thread-2");
23         Thread thread3 = new Thread(r, "thread-3");
24         Thread thread4 = new Thread(r, "thread-4");
25         
26         //开启线程
27         thread1.start();
28         thread2.start();
29         thread3.start();
30         thread4.start();
31         
32     }    
33 }
35 class TicketCenter{
36     public static int restCount = 100; 
37 }

 

 

以上是关于Java多线程的临界资源问题的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程-静态条件与临界区

Java多线程synchronized

同步互斥的实现

RT-Thread多线程导致的临界区问题

c++多线程问题

java线程同步