Java多线程中的竞争条件、锁以及同步的概念
竞争条件
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多线程中并发集合和同步集合有哪些? hashmap 是非同步的,故在多线程中是线程不安全的,不过也可以使用 同步类来进行包装: 包装类Collections.synchronizedMap() ...
- Java多线程中的常用方法
本文将带你讲诉Java多线程中的常用方法 Java多线程中的常用方法有如下几个 start,run,sleep,wait,notify,notifyAll,join,isAlive,current ...
- Java多线程中的死锁
Java多线程中的死锁 死锁产生的原因 线程死锁是指由两个以上的线程互相持有对方所需要的资源,导致线程处于等待状态,无法往前执行. 当线程进入对象的synchronized代码块时,便占有了资源,直到 ...
- java多线程中的三种特性
java多线程中的三种特性 原子性(Atomicity) 原子性是指在一个操作中就是cpu不可以在中途暂停然后再调度,既不被中断操作,要不执行完成,要不就不执行. 如果一个操作时原子性的,那么多线程并 ...
- java 多线程中的wait方法的详解
java多线程中的实现方式存在两种: 方式一:使用继承方式 例如: PersonTest extends Thread{ String name; public PersonTest(String n ...
- java多线程中最佳的实践方案是什么?
java多线程中最佳的实践方案是什么? 给你的线程起个有意义的名字.这样可以方便找bug或追踪.OrderProcessor, QuoteProcessor or TradeProcessor 这种名 ...
- java 多线程中的锁的类别及使用
目前在Java中存在两种锁机制: synchronized Lock Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug Lea. 数据同步需要依赖锁,那锁的同步又依赖谁? ...
- java多线程中的死锁、活锁、饥饿、无锁都是什么鬼?
死锁.活锁.饥饿是关于多线程是否活跃出现的运行阻塞障碍问题,如果线程出现了这三种情况,即线程不再活跃,不能再正常地执行下去了. 死锁 死锁是多线程中最差的一种情况,多个线程相互占用对方的资源的锁,而又 ...
- java多线程系类:JUC锁:01之框架
本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--"JUC锁"01之 框架02. Java多线程系列--"JUC锁&q ...
随机推荐
- [读书笔记] CSS揭秘-背景与边框
半透明边框 默认情况下,背景会延伸到边框所在的区域下层.可以通过background-clip属性调整该默认行为. border: 10px solid rgba(0,0,0,.2) backgrou ...
- 分布式协调服务Zookeeper
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提供的功 ...
- 初识交替最小二乘ALS
ALS是alternating least squares的缩写 , 意为交替最小二乘法:而ALS-WR是alternating-least-squares with weighted-λ -regu ...
- 移动 web 1px 边框解决方案
在移动端web页面开发中,为了使css中使用的尺寸与设计稿一致,通常会采用 rem 单位配合 lib-flexible 来实现移动端的适配,在IOS设备上 flexible.js 会根据设备的分辨率动 ...
- Tiny4412在Ubuntu下给MiniTools添加快捷方式
解压MiniTools-Linux-20140317.tgz root@ubuntu:~/tiny4412/MiniTools-# ls -l total -rw-r--r-- root root M ...
- ASIHTTPREQUEST framework compile error when method is called / link error
never mind!!! duplicate: Error with iOS 5.1 when i use ASIHTTPRequest and SBJSON "I would take ...
- hibernate.cfg.xml配置文件对关联关系的书写技巧!
以Department(部门类)和User(用户类)作为例子: 类图如下: 一般hibernate.cfg.xml的配置文件开头都是如下: <?xml version="1.0&quo ...
- python 读取CSV文件 中文乱码
今天读取一个CSV文件,打印出来,中文显示乱码,原因是编码的缘故,CSV保存是编码格式ANSI,解决办法是以记事本方式打开CSV文件,然后另存为时编码选择UTF-8进行保存即可.
- 【Hadoop】Hadoop MR Job工作流引擎
Apache Oozie 是用于 Hadoop 平台的一种工作流调度引擎.该框架(如图 1 所示)使用 Oozie 协调器促进了相互依赖的重复工作之间的协调,您可以使用预定的时间或数据可用性来触发 A ...
- 【Java编码准则】の #13使用散列函数保存password
明文保存password的程序在非常多方面easy造成password的泄漏.尽管用户输入的password一般时明文形式.可是应用程序必须保证password不是以明文形式存储的. 限制passwo ...