【Java 深入学习】一个关于“锁”的程序 - 中
与前文衔接的地方
可以看到线程 1 已经卖到了第 82 张票但此时线程 0 又卖了一次之前的第 100 张票,它的逻辑是这样的:最开始线程 1 运行了 System.out.printf(“%s 线程正在卖出第 %d 张票\n”,Thread.currentThread().getName(),tickets);语句但是并没有减 1,然后切换到了线程 0,然后线程 0 已经加载了 System.out.printf(“%s 线程正在卖出第 %d 张票\n”,Thread.currentThread().getName(),tickets);语句但此时还没有来的及输出(注意:因为输出语句已经加载好 所以此时要输出的应该是 Thread-0 线程正在卖出第 100 张票 只是没有来得及输出),之后又切换到了线程 1 继续从上次线程 1 运行的地方运行 此时运行 tickets–;,然后一直到 Thread-0 线程正在卖出第 100 张票之前都是线程 1 在正常运行 运行到 Thread-1 线程正在卖出第 82 张票,此时切换到线程 0 因为之前线程 0 已经加载了==System.out.printf(“%s 线程正在卖出第 %d 张票\n”,Thread.currentThread().getName(),tickets);所以继续从这里运行 所以接下来运行 System.out.printf(“%s 线程正在卖出第 %d 张票\n”,Thread.currentThread().getName(),tickets);语句输出 Thread-0 线程正在卖出第 100 张票 但是此时的票数实际上是 81 然后线程 0 运行 tickets–==后 此时票数是 80,所以之后线程 0 才会输入 Thread-0 线程正在卖出第 80 张票,那么第 81 张呢?其实第 81 张也是和第 100 张的情况一样,第 81 张被线程 1 的输出语句加载但还没有输出 但是之后 再次切换到线程 1 时会再次输出 81。
线程同步
知识了解
线程同步实际上是通过 synchronized 关键字实现的,它的作用是规定一个锁 这个锁可以锁定一块代码段也可以锁定一个方法, 这个锁 锁住一个公共对象 只有拿到这个锁的线程才可以运行锁内部的代码且不可被打断 直到这块代码运行完毕 释放锁 之后所有线程再来争抢锁。这样做的目的是为了 公共资源部分的代码在同一时刻只能由一个线程运行,避免线程不安全。对于卖票程序来说 它们的公共资源的就是 票池 锁住的部分就是卖票和票数减一。实质上 锁 锁住的对象叫做监听器 锁住对象的动作叫做锁定。
代码示例
PS:synchronized 总结:格式:synchronized(类对象名 aa){同步代码块}synchronized(类对象名 aa)的含义是:判断 aa 是否已经被其他线程霸占,如果发现已经被其他线程霸占,则当前线程陷入等待,如果发现 aa 没有被其他线程霸占,则当前线程霸占注 aa 对象,并执行 3 行的代码同步块,在当前线程执行 3 行代码时,其他线程将无法再执行 3 行的代码(因为当前线程以及霸占了 aa 对象),当前线程执行完 3 行的代码后,会自动释放对 aa 对象的霸占,此时其他线程会相互竞争对 aa 的霸占,最终 cpu 会选择其中的某一个线程执行
补充:霸占的专业术语叫做锁定,霸占住的那个对象专业术语叫做监听器,监听器可以是 this 指向的那个对象也可以是类里的其他对象。
锁定类似于 有 n 个人上厕所 有一个厕所牌 只有当某人拿到厕所牌才可以上厕所,关键点在于只有一个厕所牌 即厕所牌是公共的,区别在于是哪个人拿了厕所牌 则锁定那个人的厕所牌 如果上完厕所则 其他人再争抢厕所牌。
当修饰代码块时需要(类对象名 aa),当修饰方法时 则不需要只需要在方法前加上 synchronized 不需要括号 默认监听器是 this。
当在运行同步代码块时,线程是可以随机改变的 只不过因为线程的监听器被锁定 导致其他的线程的监听器无法被锁定 导致只有监听器被锁定的那个线程运行完同步代码块后 把监听器释放 才能让其他线程的监听器取竞争。
当在创建线程时,只有写法一是对的,写法二虽然也创建了两个线程 但这两个线程的 synchronized 没有锁定的关系,依旧会出现代码不同步的问题。
如果保证写法二也是正确的 则必须保证 有唯一的厕所牌 即 公共对象,这个公共对象不能是 this 因为 this 会指向不同的对象,所以这种情况下 必须用一个公共的类对象 才能保证写法二正确,但写法一则不用考虑 因为这个的公共对象就是 aa
推荐使用写法一
结果:
测试了一万张票,没有出现错误。
版权声明: 本文为 InfoQ 作者【Geek_65222d】的原创文章。
原文链接:【http://xie.infoq.cn/article/bf08df1e6f0758e6780cd212c】。未经作者许可,禁止转载。
评论