Java多线程中的竞争条件、锁以及同步的概念
2017-07-05 11:40
267 查看
竞争条件
1.竞争条件:
在java多线程中,当两个或以上的线程对同一个数据进行操作的时候,可能会产生“竞争条件”的现象。这种现象产生的根本原因是因为多个线程在对同一个数据进行操作,此时对该数据的操作是非“原子化”的,可能前一个线程对数据的操作还没有结束,后一个线程又开始对同样的数据开始进行操作,这就可能会造成数据结果的变化未知。
package com.huojg.test; public class TestThread { public static void main(String[] args) { // new 出一个新的对象 t MyThread t = new MyThread(); /** * 两个线程是在对同一个对象进行操作 */ Thread ta = new Thread(t, "Thread-A"); Thread tb = new Thread(t, "Thread-B"); ta.start(); tb.start(); } } class MyThread implements Runnable { // 变量 a 被两个线程共同操作,可能会造成线程竞争 int a = 10; @Override public void run() { for (int i = 0; i < 5; i++) { a -= 1; try { Thread.sleep(1); } catch (InterruptedException e) {} System.out.println(Thread.currentThread().getName() + " → a = " + a); } } }
结果显示:
Thread-A → a = 8 Thread-B → a = 8 Thread-A → a = 6 Thread-B → a = 6 Thread-B → a = 4 Thread-A → a = 4 Thread-B → a = 2 Thread-A → a = 2 Thread-A → a = 0 Thread-B → a = 0
从上面的结果中我们可以看到,在线程A对数据进行了操作之后,他还没有来得及数据进行下一次的操作,此时线程B也对数据进行了操作,导致数据a一次性被减了两次,以至于a为9的时候的值根本没有打印出来,a为0的时候却被打印了两次。
那么,我们要如何才能避免结果这种情况的出现呢?
2.线程锁
如果在一个线程对数据进行操作的时候,禁止另外一个线程操作此数据,那么,就能很好的解决以上的问题了。这种操作叫做给线程加锁。
package com.huojg.test; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 在Java多线程中,当两个或以上的线程对同一个数据进行操作的时候,可能会产生“竞争条件”的现象。这种现象产生的根本原因是因为多个线程在对同一个数据进行操作,此时对该数据的操作是非“原子化”的, * 可能前一个线程对数据的操作还没有结束,后一个线程又开始对同样的数据开始进行操作,这就可能会造成数据结果的变化未知。 * * * 2.线程锁 如果在一个线程对数据进行操作的时候,禁止另外一个线程操作此数据,那么,就能很好的解决以上的问题了。这种操作叫做给线程加锁。 * */ public class TestThread { public static void main(String[] args) { // new 出一个新的对象 t MyThread t = new MyThread(); /** * 两个线程是在对同一个对象进行操作 */ Thread ta = new Thread(t, "Thread-A"); Thread tb = new Thread(t, "Thread-B"); ta.start(); tb.start(); } } class MyThread implements Runnable { // 声明锁 private Lock lock = new ReentrantLock(); // 变量 a 被两个线程共同操作,可能会造成线程竞争 int a = 10; @Override public void run() { // 加锁 lock.lock(); for (int i = 0; i < 5; i++) { a -= 1; try { Thread.sleep(1); } catch (InterruptedException e) {} System.out.println(Thread.currentThread().getName() + " → a = " + a); } lock.unlock(); } }
运行结果:
Thread-A → a = 9 Thread-A → a = 8 Thread-A → a = 7 Thread-A → a = 6 Thread-A → a = 5 Thread-B → a = 4 Thread-B → a = 3 Thread-B → a = 2 Thread-B → a = 1 Thread-B → a = 0
上面的代码给出了给线程枷锁的方式,可以看到,在线程对数据进行操作之前先给此操作加一把锁,那么在此线程对数据进行操作的时候,其他的线程无法对此数据进行操作,只能“阻塞”在一边等待当前线程对数据操作结束后再对数据进行下一次的操作,当前线程在数据的操作完成之后会解开当前的锁以便下一个线程操作此数据
用synchronized关键字加锁来对方法进行加锁:结果一样;
总结:
Java中的多线程,当多个线程对一个数据进行操作时,可能会产生“竞争条件”的现象,这时候需要对线程的操作进行加锁,来解决多线程操作一个数据时可能产生问题。加锁方式有两种,一个是申明Lock对象来对语句快进行加锁,另一种是通过synchronized 关键字来对方法进行加锁。以上两种方法都可以有效解决Java多线程中存在的竞争条件的问题。
相关文章推荐
- Java多线程中的竞争条件、锁以及同步的概念
- java多线程的同步 通信以及生产消费者问题
- [多线程]环形缓冲区以及多线程条件同步
- JAVA多线程(二)竞态条件、死锁及同步机制
- Java多线程产生死锁的条件以及解决方法
- Java多线程简析——Synchronized(同步锁)、Lock以及线程池
- java多线程的同步 通信以及生产消费者问题
- 从头认识java-17.4 详解同步(2)-详解竞争条件
- Java多线程wait,notify以及同步锁的运用实例
- JAVA多线程(二)竞态条件、死锁及同步机制
- 什么是多线程中的竞争条件 - Java中的2个示例
- JAVA多线程中,原子操作的概念——原子操作真的不需要进行同步控制吗?
- java线程同步——竞争条件的荔枝+锁对象
- 【搞懂Java多线程之一】多线程相关概念,线程生命周期以及线程创建方法
- Java核心技术学习---多线程,锁,同步,条件对象部分应用源码
- java多线程实现火车售票系统 以及java中的同步的实现 同步块 和同步方法同时 同步
- JAVA多线程并发同步,以及线程终止
- 黑马程序员-------------多线程中的(线程、线程组、线程池、以及Java的设计模式)概念及方法的总结
- Java(8-2)多线程的同步和条件对象
- 从头认识java-17.4 具体解释同步(2)-具体解释竞争条件