11 临界区与竞态条件

11 临界区与竞态条件

临界区 Critical Section

  • 一个程序运行多个线程本身是没有问题的

  • 问题出在多个线程访问共享资源

    • 多个线程读共享资源其实也没有问题

    • 在多个线程对共享资源读写操作时发生指令交错,就会出现问题

  • 一段代码块内如果存在对共享资源的多线程读写操作,称这段代码块为临界区

例如,下面代码中的临界区:

static int counter = 0;
static void increment() 
// 临界区
{ 
counter++;
}
static void decrement() 
// 临界区
{ 
counter--;
}

竞态条件 Race Condition

多个线程在临界区内执行,由于代码的执行序列不同而导致结果无法预测,称之为发生了竞态条件

临界区资源加锁和不加锁的代码演示

//对临界区不加锁,会产生不正确的答案
public class CriticalZoneAndLock {
   static int count = 0;
   static Object lock = new Object();
   public static void main(String[] args) throws InterruptedException {
       Runnable task1 = new Runnable() {
           @Override
           public void run() {
               //对临界区资源加同一把锁
//                synchronized (lock){
                   //临界区
                   for (int i = 0; i < 5000; i++) {
                       count++;
                   }
//                }

           }
       };

       Runnable task2 = new Runnable() {
           @Override
           public void run() {
               //对临界区资源加同一把锁
               //synchronized (lock){
                   //临界区
                   for (int i = 0; i < 5000; i++) {
                       count--;
                   }
               }
           //}
       };
       Thread t1 = new Thread(task1, "t1");
       Thread t2 = new Thread(task2, "t2");

       t1.start();
       t2.start();
       t1.join();
       t2.join();

       System.out.println(count);
   }
}

结果:

-272(这个数是随机的)

public class CriticalZoneAndLock {
   static int count = 0;
   static Object lock = new Object();

   public static void main(String[] args) throws InterruptedException {
       Runnable task1 = new Runnable() {
           @Override
           public void run() {
               //对临界区资源加同一把锁
               synchronized (lock) {
                   //临界区
                   for (int i = 0; i < 5000; i++) {
                       count++;
                   }
               }
           }
       };

       Runnable task2 = new Runnable() {
           @Override
           public void run() {
               //对临界区资源加同一把锁
               synchronized (lock) {
                   //临界区
                   for (int i = 0; i < 5000; i++) {
                       count--;
                   }
               }
           }
       };
       Thread t1 = new Thread(task1, "t1");
       Thread t2 = new Thread(task2, "t2");

       t1.start();
       t2.start();
       t1.join();
       t2.join();

       System.out.println(count);
   }
}

结果:

0

posted @   渺阴丶  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示