使用同步锁实现丈夫和妻子去世丈夫禁忌取钱的过程

iOS之同步锁 - CSDN博客
iOS之同步锁
iOS中的几种同步锁:
1、OSSpinLock 自旋锁,性能最高的锁。原理很简单,就是一直 do while 忙等。它的缺点是当等待时会消耗大量 CPU 资源,所以它不适用于较长时间的任务。对于内存缓存的存取来说,它非常合适。
自旋锁几乎不进入内核,仅仅是重新加载自旋锁。 如果自旋锁被占用时间是几十,上百纳秒,性能还是挺高的。减少了代价较高的系统调用和一系列上下文言切换。 但是,该锁不是万能的;如果该锁抢占比较多的时候,不要使用该锁。会占用较多cpu,导致耗电较多。 这种情况下使用pthread_mutex或者dispatch_semaphore。虽然耗时多一点,但是避免了电量过多的消耗。是不错的选择。
官方描述: Spin locks are a simple, fast, thread-safe synchronization primitive that
is suitable in situations
where contention is expected to be low. The spinlock operations use memory barriers to synchronize access to shared memory
protected by the
lock. Preemption is possible
while the lock
2、dispatch_semaphore 是信号量,但当信号总量设为 1 时也可以当作锁来。在没有等待情况出现时,它的性能比 pthread_mutex 还要高,但一旦有等待情况出现时,性能就会下降许多。相对于 OSSpinLock 来说,它的优势在于等待时不会消耗 CPU 资源。对磁盘缓存来说,它比较合适。
3、使用NSLock实现的锁
4、使用synchronized关键字构建的锁。@synchronized指令使用的obj为该锁的唯一标识,只有当标识相同时,才为满足互斥,如果线程2中的@synchronized(obj)改为@synchronized(other),刚线程2就不会被阻塞,@synchronized指令实现锁的优点就是我们不需要在代码中显式的创建锁对象,便可以实现锁的机制,但作为一种预防措施,@synchronized块会隐式的添加一个异常处理例程来保护代码,该处理例程会在异常抛出的时候自动的释放互斥锁。所以如果不想让隐式的异常处理例程带来额外的开销,你可以考虑使用锁对象。
5、使用C语言的pthread_mutex_t实现的锁。pthread_mutex_t定义在pthread.h,所以记得#include,底层的API还是性能比较高啊,在各种同步对象中,性能属于佼佼者。
6、NSConditionLock、NSCondition条件锁:当我们在使用多线程的时候,有时一把只会lock和unlock的锁未必就能完全满足我们的使用。因为普通的锁只能关心锁与不锁,而不在乎用什么钥匙才能开锁,而我们在处理资源共享的时候,多数情况是只有满足一定条件的情况下才能打开这把锁。与特定的,用户定义的条件有关。可以确保一个线程可以获取满足一定条件的锁。
内部会涉及到信号量机制,一旦一个线程获得锁后,它可以放弃锁并设置相关条件;其它线程竞争该锁。 线程之间的竞争激烈,涉及到条件锁检测,线程间通信。系统调用,上下切换方切换比较频繁
7、NSRecursiveLock递归锁 ,也就说可以锁多次,@synchronized也是递归锁;
8、NSDistributedLock分布式锁 &(不熟)
9、所有的锁都可以用同步解决,不过那样效率很低,因为同步是另开一个线程去执行一段代码然后返回结果,同时原来的线程等待被唤醒,这样会多耗费资源。
耗时方面:
OSSpinlock耗时最少;
pthread_mutex其次。
NSLock/NSCondition/NSRecursiveLock 耗时接近,上下居中。
NSConditionLock最差,我们常用synchronized倒数第二。
如果只是粗略的使用锁,不考虑性能问题可以使用synchronized。
如果对效率有较高的要求,还是采用OSSpinlock比较好。
因为Pthread的锁在也是用 OSSpinlock 实现的。OSSpinlock 的实现过程中,并没有进入系统kernel,使用OSSpinlock可以节省系统调用和上下文切换。
最简单的死锁(在主线程调用同步):
dispatch_sync(dispatch_get_main_queue(), ^{
&&&&&// do something
下面是Demo:
__weak typeof (self) weakself =
///*************NSLock 锁对象***************/
// //主线程中
// NSLock *lock = [[NSLock alloc] init];
// //线程1
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[lock lock];
[weakself method1];
sleep(10);
[lock unlock];
// //线程2
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);//以保证让线程2的代码后执行
[lock lock];
[weakself method2];
[lock unlock];
///*************@synchronized 关键锁***************/
// //线程1
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(weakself){
[weakself method1];
sleep(10);
// //线程2
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(weakself){
[weakself method2];
///*************pthread_mutex_t 锁***************/
// __block pthread_mutex_
// pthread_mutex_init(&mutex, NULL);
// //线程1
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
pthread_mutex_lock(&mutex);
[weakself method1];
pthread_mutex_unlock(&mutex);
// //线程2
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
pthread_mutex_lock(&mutex);
[weakself method2];
pthread_mutex_unlock(&mutex);
// /*************dispatch_semaphore_t GCD(信号量)锁***************/
// /*dispatch_semaphore_create、dispatch_semaphore_signal、dispatch_semaphore_wait
// 简单的介绍一下这三个函数,第一个函数有一个整形的参数,我们可以理解为信号的总量,dispatch_semaphore_signal是发送一个信号,自然会让信号总量加1,dispatch_semaphore_wait等待信号,当信号总量少于0的时候就会一直等待,否则就可以正常的执行,并让信号总量-1,根据这样的原理,我们便可以快速的创建一个并发控制来同步任务和有限资源访问控制*/
// dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
// //线程1
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[weakself method1];
sleep(10);
dispatch_semaphore_signal(semaphore);
// //线程2
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[weakself method2];
dispatch_semaphore_signal(semaphore);
///*************NSConditionLock
条件锁***************/
// /*这段代码执行顺序会有问题,如果线程2来不及锁又会被线程1锁住,这样线程2就不会执行。*/
// NSConditionLock *lock1 = [[NSConditionLock alloc]init];
// //线程1
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (int i=0 ; i&=2 ; i++){
[lock1 lock];
NSLog(@&线程1&);
[lock1 unlockWithCondition:i];
// //线程2
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[lock1 lockWhenCondition:1];
NSLog(@&线程2&);
[lock1 unlock];
// __block NSString *stringV
// dispatch_sync(dispatch_get_main_queue(), ^{
// __block variables aren't automatically retained
// so we'd better make sure we have a reference we can keep
stringValue = @&--------&&&;
// NSLog(@&%@&,stringValue);
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[weakself method3:@&thread1&];
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[weakself method3:@&thread1&];
- (void)method1
NSLog(@&%@&,NSStringFromSelector(_cmd));
NSLog(@&%s&,__FUNCTION__);
- (void)method2
NSLog(@&%@&,NSStringFromSelector(_cmd));
NSLog(@&%s&,__func__);
- (void)method3:(NSString *)thread{
NSString *str = @&&;
@synchronized(thread) {
NSLog(@&%p&,str);
本文已收录于以下专栏:
相关文章推荐
看到标题,我想大部分iOS开发的童鞋能想到好几种方案。比如下一个网络请求必须依赖上一个网络请求的结果才可以进行,最简单直白的方法是:“同步调用”。这里所说的同步是指,等上一个网络请求任务完成后,直接在...
线程同步说到多线程就不得不提多线程的锁机制,多线程操作过程中往往是多个线程并发执行的,同一个资源可能被多个线程同时访问,造成资源抢夺,这个时候如果没有锁机制会造成很大的问题。举个例子比如买票系统比如只...
申明:此为本人学习笔记,若有纰漏错误之处的可留言共同探讨
情景:哆啦A梦、大雄、胖虎三人各自在自己的手机上买火车票想去富士山旅游,哆啦A梦想和它妹妹一起去,想买2张票;大雄想和静香...
应用程序里面多个线程的存在引发了多个执行线程安全访问资源的潜在问题。两个线程同时修改同一资源有可能以意想不到的方式互相干扰。
提供了你可以使用的多个同步工具,从提供互斥访...
1:原子操作 - OSAtomic系列函数
iOS平台下的原子操作函数都以OSAtomic开头,使用时需要包含头文件。不同线程如果通过原子操作函数对同一变量进行操作,可以保证一个线程的操作不会影响到...
本文为投稿文章,作者:SpringOx(博客)
iOS/MacOS为多线程、共享内存(变量)提供了多种的同步解决方案(即同步锁),对于这些方案的比较,大都讨论了锁的用法以及锁操作的开销,然后就开...
我们先看一下线程状态
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[NSThread...
iOS同步锁介绍,包含@synchronized、NSLock、dispatch_semaphore、NSCondition、pthread_mutex和OSSpinLock等。...
1.NSLock---锁同步
- (void)viewDidLoad
[super viewDidLoad];
NSLock * lock = [[NSLock alloc]in...
他的最新文章
讲师:钟钦成
讲师:宋宝华
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)同步锁(lock)
编辑:www.fx114.net
本篇文章主要介绍了"同步锁(lock) ",主要涉及到同步锁(lock) 方面的内容,对于同步锁(lock) 感兴趣的同学可以参考一下。
有两种机制防止代码块受并发访问的干扰:
1、一个是使用synchronized关键字。
2、使用ReentrantLock类。(通过显示定义同步锁对象来实现同步。)
同步锁(lock)方法是控制多个线程对共享资源进行访问的工具。通常,锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前先获得Lock对象。
Lock、ReadWriteLock(读写锁)是java 5 提供的两个根接口。别为Lock接口提供了ReentrantLock(可重入锁)实现类;为ReadWriteLock接口提供了ReentrantReadWriteLock实现类。
在实现线程安全的控制中,比较常用的是ReentrantLock(可重入锁)。使用该Lock对象可以显示地加锁、释放锁。
1 import java.util.*;
2 import java.util.concurrent.locks.ReentrantL
3 public class Other extends Thread{
private double drawA
//private S
public Other(Account account,double drawAmount,String name){
super(name);//必须是第一语句
this.account=
10
this.drawAmount=drawA
11
start();
12
public void run(){
14
for(int i=0;i&15;i++){
15
account.draw(drawAmount);
16
public static void main(String[] args){
19
Account a=new Account("刘腾",10000);
20
Other o=new Other(a,1000,"A");
21
Thread t=new Thread(new RunnableClass(a));
22
t.setName("B");
23
t.start();
24
}
25 }
26 class Account{
27
//定义锁对象
28
private final ReentrantLock lock=new ReentrantLock();
29
private S
30
private double
31
public Account(){}
32
public Account(String name,double money){
33
this.name=
34
this.money=
35
public double getMoney(){
37
lock.lock();
38
return}
40
finally{
41
lock.unlock();
42
public void draw(double drawAmount){
45
lock.lock();
46
if(money&=drawAmount){
48
System.out.println(name +"取钱成功!吐出钞票:"+drawAmount);
49
Thread.sleep(1000);
51
}catch(Exception e){
52
System.out.println(e);
53
money-=drawA
55
System.out.println("余额为:"+getMoney());
56
System.out.println("取钱失败!余额不足!");
58
}finally{
60
lock.unlock();
61
}
63 }
64 class RunnableClass implements Runnable{
65
private A
66
//private double drawA
67
public RunnableClass(Account account){
68
this.account=
69
//this.drawAmount=drawA
70
public void run (){
72
for(int k=0;k&10;k++){
73
Thread.sleep(1000);
75
System.out.println(Thread.currentThread().getName()+"读取钱数为:"+account.getMoney());}
76
catch(Exception e){}
77
需要导入import java.util.concurrent.locks.ReentrantL
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:5316人阅读
面试/其他(12)
首先说明一下什么是分布式锁,维基百科的说明为:
分布式锁,是控制之间同步访问共享的一种方式。在分布式系统中,常常需要协调他们的动作。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。
在进行大型网站技术架构设计以及业务实现的过程中,多少都会遇到需要使用分布式锁的情况。那么问题也就接踵而至。分布式锁zk和memcached以及redis三者都能实现,同样是分布式锁,三者的区别何在?各自适用什么场景?
1、实现原理:
基于zookeeper瞬时有序节点实现的分布式锁,其主要逻辑如下(该图来自于IBM网站)。大致思想即为:每个客户端对某个功能加锁时,在zookeeper上的与该功能对应的指定节点的目录下,生成一个唯一的瞬时有序节点。判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。
& & & & & & & & & & & & &&
锁安全性高,zk可持久化,且能实时监听获取锁的客户端状态。一旦客户端宕机,则瞬时节点随之消失,zk因而能第一时间释放锁。这也省去了用分布式缓存实现锁的过程中需要加入超时时间判断的这一逻辑。
性能开销比较高。因为其需要动态产生、销毁瞬时节点来实现锁功能。所以不太适合直接提供给高并发的场景使用。
可以直接采用zookeeper第三方库curator即可方便地实现分布式锁。
5、适用场景
对可靠性要求非常高,且并发程度不高的场景下使用。如核心数据的定时全量/增量同步等。
memcached分布式锁
1、实现原理
memcached带有add函数,利用add函数的特性即可实现分布式锁。add和set的区别在于:如果多线程并发set,则每个set都会成功,但最后存储的值以最后的set的线程为准。而add的话则相反,add会添加第一个到达的值,并返回true,后续的添加则都会返回false。利用该点即可很轻松地实现分布式锁。
memcached采用列入LRU置换策略,所以如果内存不够,可能导致缓存中的锁信息丢失。memcached无法持久化,一旦重启,将导致信息丢失。
4、使用场景
高并发场景。需要1)加上超时时间避免死锁;2)提供足够支撑锁服务的内存空间;3)稳定的集群化管理。
redis分布式锁
redis分布式锁即可以结合zk分布式锁锁高度安全和memcached并发场景下效率很好的优点,其实现方式和memcached类似,采用setnx即可实现。需要注意的是,这里的redis也需要设置超时时间。以避免死锁。可以利用jedis客户端实现。参考资料。
原文地址://分布式锁的三种实现方式/
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:478472次
积分:7288
积分:7288
排名:第3350名
原创:212篇
转载:331篇
评论:28条
(1)(2)(1)(2)(6)(1)(3)(1)(16)(24)(7)(4)(44)(28)(51)(22)(11)(18)(7)(34)(28)(21)(8)(26)(12)(26)(15)(6)(28)(8)(5)(10)(27)(31)(9)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'1484人阅读
Java(22)
用一个卖票的例子来示范多线程操作一个对象时,同步锁的使用。
先新建一个SaleRunnable类实现Runnable接口,用于表示“卖票”过程:
class SaleRunnable implements Runnable {
private int ticket = 20;
public void run() {
while(ticket & 0) {
Log.d("Test", Thread.currentThread().getName() + "卖出了第" + (20-ticket+1) + "张票");
如上,一共有20张票,每卖出一张票,则打印卖出此票的线程名和票的序号。这个代码里没有加锁。
然后在主程序创建三个线程,传入同一个SaleRunnable对象,三个线程名分别为老王,老张,老李:
SaleRunnable r = new SaleRunnable();
Thread t1 = new Thread(r,"老王");
Thread t2 = new Thread(r,"老张");
Thread t3 = new Thread(r,"老李");
然后调用线程的start()方法启动三个线程:
t1.start();
t2.start();
t3.start();
运行结果如下:
08-26 12:55:56.011 28300-28315/? D/Test: 老王卖出了第1张票
08-26 12:55:56.011 28300-28315/? D/Test: 老王卖出了第2张票
08-26 12:55:56.011 28300-28315/? D/Test: 老王卖出了第3张票
08-26 12:55:56.011 28300-28315/? D/Test: 老王卖出了第4张票
08-26 12:55:56.011 28300-28315/? D/Test: 老王卖出了第5张票
08-26 12:55:56.011 28300-28315/? D/Test: 老王卖出了第6张票
08-26 12:55:56.011 28300-28315/? D/Test: 老王卖出了第7张票
08-26 12:55:56.011 28300-28315/? D/Test: 老王卖出了第8张票
08-26 12:55:56.011 28300-28315/? D/Test: 老王卖出了第9张票
08-26 12:55:56.011 28300-28315/? D/Test: 老王卖出了第10张票
08-26 12:55:56.011 28300-28315/? D/Test: 老王卖出了第11张票
08-26 12:55:56.011 28300-28316/? D/Test: 老张卖出了第12张票
08-26 12:55:56.011 28300-28316/? D/Test: 老张卖出了第13张票
08-26 12:55:56.011 28300-28316/? D/Test: 老张卖出了第14张票
08-26 12:55:56.011 28300-28316/? D/Test: 老张卖出了第15张票
08-26 12:55:56.011 28300-28316/? D/Test: 老张卖出了第16张票
08-26 12:55:56.011 28300-28316/? D/Test: 老张卖出了第17张票
08-26 12:55:56.011 28300-28316/? D/Test: 老张卖出了第18张票
08-26 12:55:56.011 28300-28316/? D/Test: 老张卖出了第19张票
08-26 12:55:56.011 28300-28316/? D/Test: 老张卖出了第20张票
08-26 12:55:56.011 28300-28315/? D/Test: 老王卖出了第12张票
可见其结果是乱的,重复运行多次,结果不一,但是都没实现正常的卖票效果。为什么呢,因为三个线程在并行操作同一个对象,所以会出现老张的线程和老王的线程都卖出了第12张票的情况,但是这显然是不对的。
怎么办呢,修改下SaleRunnable类,加上锁试试:
class SaleRunnable implements Runnable {
private int ticket = 20;
public void run() {
while(ticket & 0) {
synchronized(this) {
Log.d("Test", Thread.currentThread().getName() + "卖出了第" + (20 - ticket + 1) + "张票");
如上面所示,把锁加在判断条件里面,运行结果:
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第1张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第2张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第3张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第4张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第5张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第6张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第7张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第8张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第9张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第10张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第11张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第12张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第13张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第14张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第15张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第16张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第17张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第18张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第19张票
08-26 13:15:08.621 15256-15271/? D/Test: 老王卖出了第20张票
08-26 13:15:08.631 15256-15273/? D/Test: 老李卖出了第21张票
08-26 13:15:08.631 15256-15272/? D/Test: 老张卖出了第22张票
结果看,虽然卖票顺序对了,但卖多了也是不正常的,再改下:
class SaleRunnable implements Runnable {
private int ticket = 20;
public void run() {
synchronized(this){
while(ticket & 0) {
Log.d("Test", Thread.currentThread().getName() + "卖出了第" + (20 - ticket + 1) + "张票");
运行结果:
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第1张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第2张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第3张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第4张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第5张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第6张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第7张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第8张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第9张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第10张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第11张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第12张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第13张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第14张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第15张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第16张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第17张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第18张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第19张票
08-26 13:31:41.061 31687-31724/? D/Test: 老王卖出了第20张票
结果是没错,但是票全让老王给卖了,这也不正常,因为我们把锁加在整个卖票操作外面了,一旦老王开始卖票,其他人都没法卖了。再改:
class SaleRunnable implements Runnable {
private int ticket = 20;
public void run() {
while(true) {
synchronized(this) {
if (ticket & 0) {
Log.d("Test", Thread.currentThread().getName() + "卖出了第" + (20 - ticket + 1) + "张票");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
这样修改后结果正常了:
08-26 13:43:24.181 12176-12199/? D/Test: 老王卖出了第1张票
08-26 13:43:24.181 12176-12200/? D/Test: 老张卖出了第2张票
08-26 13:43:24.181 12176-12201/? D/Test: 老李卖出了第3张票
08-26 13:43:27.181 12176-12199/?D/Test: 老王卖出了第4张票
08-26 13:43:27.181 12176-12200/?D/Test: 老张卖出了第5张票
08-26 13:43:27.181 12176-12201/?D/Test: 老李卖出了第6张票
08-26 13:43:30.181 12176-12199/?D/Test: 老王卖出了第7张票
08-26 13:43:30.181 12176-12200/?D/Test: 老张卖出了第8张票
08-26 13:43:30.181 12176-12201/?D/Test: 老李卖出了第9张票
08-26 13:43:33.181 12176-12199/?D/Test: 老王卖出了第10张票
08-26 13:43:33.181 12176-12200/?D/Test: 老张卖出了第11张票
08-26 13:43:33.181 12176-12201/?D/Test: 老李卖出了第12张票
08-26 13:43:36.181 12176-12199/?D/Test: 老王卖出了第13张票
08-26 13:43:36.181 12176-12200/?D/Test: 老张卖出了第14张票
08-26 13:43:36.191 12176-12201/?D/Test: 老李卖出了第15张票
08-26 13:43:39.181 12176-12199/?D/Test: 老王卖出了第16张票
08-26 13:43:39.181 12176-12200/?D/Test: 老张卖出了第17张票
08-26 13:43:39.191 12176-12201/?D/Test: 老李卖出了第18张票
08-26 13:43:42.181 12176-12199/?D/Test: 老王卖出了第19张票
08-26 13:43:42.181 12176-12200/?D/Test: 老张卖出了第20张票
因此多个线程对同一个线程进行操作时,加锁是有效的解决冲突的方式,但是加到哪里一定要多多思考。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:51572次
积分:1143
积分:1143
排名:千里之外
原创:64篇
(2)(3)(4)(5)(9)(2)(4)(2)(1)(4)(3)(6)(3)(2)(2)(9)(3)(1)(1)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'

我要回帖

更多关于 丈夫植物人妻子怀孕 的文章

 

随机推荐