多线程同步java用哪种方法实现多线程同步比较好

多线程同步  时间:2021-07-13  阅读:()

多线程同步时几个的具体区别和应用场合?

1、 Event  用事件(Event)来同步线程是最具弹性的了。

一个事件有两种状态:激发状态和未激发状态。

也称有信号状态和无信号状态。

事件又分两种类型:手动重置事件和自动重置事件。

手动重置事件被设置为激发状态后,会唤醒所有等待的线程,而且一直保持为激发状态,直到程序重新把它设置为未激发状态。

自动重置事件被设置为激发状态后,会唤醒“一个”等待中的线程,然后自动恢复为未激发状态。

所以用自动重置事件来同步两个线程比较理想。

MFC中对应的类为CEvent.。

CEvent的构造函数默认创建一个自动重置的事件,而且处于未激发状态。

共有三个函数来改变事件的状态:SetEvent,ResetEvent和PulseEvent。

用事件来同步线程是一种比较理想的做法,但在实际的使用过程中要注意的是,对自动重置事件调用SetEvent和PulseEvent有可能会引起死锁,必须小心。

  多线程同步-event  在所有的内核对象中,事件内核对象是个最基本的。

它包含一个使用计数(与所有内核对象一样),一个BOOL值(用于指明该事件是个自动重置的事件还是一个人工重置的事件),还有一个BOOL值(用于指明该事件处于已通知状态还是未通知状态)。

事件能够通知一个线程的操作已经完成。

有两种类型的事件对象。

一种是人工重置事件,另一种是自动重置事件。

他们不同的地方在于:当人工重置的事件得到通知时,等待该事件的所有线程均变为可调度线程。

当一个自动重置的事件得到通知时,等待该事件的线程中只有一个线程变为可调度线程。

  当一个线程执行初始化操作,然后通知另一个线程执行剩余的操作时,事件使用得最频繁。

在这种情况下,事件初始化为未通知状态,然后,当该线程完成它的初始化操作后,它就将事件设置为已通知状态,而一直在等待该事件的另一个线程在事件已经被通知后,就变成可调度线程。

  当这个进程启动时,它创建一个人工重置的未通知状态的事件,并且将句柄保存在一个全局变量中。

这使得该进程中的其他线程能够非常容易地访问同一个事件对象。

程序一开始创建了三个线程,这些线程在初始化后就被挂起,等待事件。

这些线程要等待文件的内容读入内存,然后每个线程都会访问这段文件内容。

一个线程进行单词计数,另一个线程运行拼写检查,第三个线程运行语法检查。

这3个线程函数的代码的开始部分都相同,每个函数都调用WaitForSingleObject.,这将使线程暂停运行,直到文件的内容由主线程读入内存为止。

一旦主线程将数据准备好,它就调用SetEvent,给事件发出通知信号。

这时,系统就使所有这3个辅助线程进入可调度状态,它们都获得了C P U时间,并且可以访问内存块。

这3个线程都必须以只读方式访问内存,否则会出现内存错误。

这就是所有3个线程能够同时运行的唯一原因。

如果计算机上配有三个以上CPU,理论上这个3个线程能够真正地同时运行,从而可以在很短的时间内完成大量的操作  如果你使用自动重置的事件而不是人工重置的事件,那么应用程序的行为特性就有很大的差别。

当主线程调用S e t E v e n t之后,系统只允许一个辅助线程变成可调度状态。

同样,也无法保证系统将使哪个线程变为可调度状态。

其余两个辅助线程将继续等待。

已经变为可调度状态的线程拥有对内存块的独占访问权。

  让我们重新编写线程的函数,使得每个函数在返回前调用S e t E v e n t函数(就像Wi n M a i n函数所做的那样)。

  当主线程将文件内容读入内存后,它就调用SetEvent函数,这样操作西永就会使这三个在等待的线程中的一个成为可调度线程。

我们不知道系统将首先选择哪个线程作为可调度线程。

当该线程完成操作时,它也将调用S e t E v e n t函数,使下一个被调度。

这样,三个线程会以先后顺序执行,至于什么顺序,那是操作系统决定的。

所以,就算每个辅助线程均以读/写方式访问内存块,也不会产生任何问题,这些线程将不再被要求将数据视为只读数据。

  这个例子清楚地展示出使用人工重置事件与自动重置事件之间的差别。

  P u l s e E v e n t函数使得事件变为已通知状态,然后立即又变为未通知状态,这就像在调用S e t E v e n t后又立即调用R e s e t E v e n t函数一样。

如果在人工重置的事件上调用P u l s e E v e n t函数,那么在发出该事件时,等待该事件的任何一个线程或所有线程将变为可调度线程。

如果在自动重置事件上调用P u l s e E v e n t函数,那么只有一个等待该事件的线程变为可调度线程。

如果在发出事件时没有任何线程在等待该事件,那么将不起任何作用[2]。

  2、 Critical Section  使用临界区域的第一个忠告就是不要长时间锁住一份资源。

这里的长时间是相对的,视不同程序而定。

对一些控制软件来说,可能是数毫秒,但是对另外一些程序来说,可以长达数分钟。

但进入临界区后必须尽快地离开,释放资源。

如果不释放的话,会如何?答案是不会怎样。

如果是主线程(GUI线程)要进入一个没有被释放的临界区,呵呵,程序就会挂了!临界区域的一个缺点就是:Critical Section不是一个核心对象,无法获知进入临界区的线程是生是死,如果进入临界区的线程挂了,没有释放临界资源,系统无法获知,而且没有办法释放该临界资源。

这个缺点在互斥器(Mutex)中得到了弥补。

Critical Section在MFC中的相应实现类是CcriticalSection。

CcriticalSection::Lock()进入临界区,CcriticalSection::UnLock()离开临界区。

  3、 Mutex  互斥器的功能和临界区域很相似。

区别是:Mutex所花费的时间比Critical Section多的多,但是Mutex是核心对象(Event、Semaphore也是),可以跨进程使用,而且等待一个被锁住的Mutex可以设定TIMEOUT,不会像Critical Section那样无法得知临界区域的情况,而一直死等。

MFC中的对应类为CMutex。

Win32函数有:创建互斥体CreateMutex() ,打开互斥体OpenMutex(),释放互斥体ReleaseMutex()。

Mutex的拥有权并非属于那个产生它的线程,而是最后那个对此Mutex进行等待操作(WaitForSingleObject等等)并且尚未进行ReleaseMutex()操作的线程。

线程拥有Mutex就好像进入Critical Section一样,一次只能有一个线程拥有该Mutex。

如果一个拥有Mutex的线程在返回之前没有调用ReleaseMutex(),那么这个Mutex就被舍弃了,但是当其他线程等待(WaitForSingleObject等)这个Mutex时,仍能返回,并得到一个WAIT_ABANDONED_0返回值。

能够知道一个Mutex被舍弃是Mutex特有的。

  4、 Semaphore  信号量是最具历史的同步机制。

信号量是解决producer/consumer问题的关键要素。

对应的MFC类是Csemaphore。

Win32函数CreateSemaphore()用来产生信号量。

ReleaseSemaphore()用来解除锁定。

Semaphore的现值代表的意义是目前可用的资源数,如果Semaphore的现值为1,表示还有一个锁定动作可以成功。

如果现值为5,就表示还有五个锁定动作可以成功。

当调用Wait…等函数要求锁定,如果Semaphore现值不为0,Wait…马上返回,资源数减1。

当调用ReleaseSemaphore()资源数加1,当时不会超过初始设定的资源总数。

线程同步几种方式

线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等。

当多个线程同时读写同一份共享资源的时候,可能会引起冲突。

这时候,我们需要引入线程“同步”机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团。

线程同步的真实意思和字面意思恰好相反。

线程同步的真实意思,其实是“排队”:几个线程之间要排队,一个一个对共享资源进行操作,而不是同时进行操作。

线程同步的方法 (1)wait():使一个线程处于等待状态,并且释放所持有的对象的lock。

(2)sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉 interruptedexception异常。

(3)notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的 唤醒某一个等待状态的线程,而是由jvm确定唤醒哪个线程,而且不是按优先级。

(4)notityall ():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁, 而是让它们竞争

JAVA 多线程同步概念

加入一个程序里的一个方法有以下输出,这两个输出需要一起执行: println("第"+i+"个线程连接"); println("你好啊,"+i+"号"); 然后有两个线程连调用了这个方法,分别叫他们1和2线程 本来我想要的输出应该是: 第1个线程连接 你好啊,1号 第2个线程连接 你好啊,2号 但是如果不加同步的话,极有可能导致如下输出: 第1个线程连接 第2个线程连接 你好啊,2号 你好啊,1号 这显然不是我想要的。

再比如银行系统,个人账户的存、取操作也应该是同步的 如果我的余额是10元,我想在线买一个15元的东西,我的余额不足,于是我充值5元,再消费15元。

由于操作的目标都是余额属性,所以多线程不同步的情况下,极有可能是先执行了消费操作后执行存钱操作。

这种情况下我的余额是不足的,导致操作不成功。

但事实是,在他判定我余额的后一秒钟存钱动作执行了,其实我的余额是够的。

这就导致了一个错误。

同步锁只是保证执行顺序,而不是说这一个方法大家在排队

什么是线程的同步?为什么要实现线程的同步?

线程同步:是多个线程同时访问同一资源,等待资源访问结束,浪费时间,效率低 线程异步:访问资源时在空闲等待时同时访问其他资源,实现多线程机制 异步处理就是,你现在问我问题,我可以不回答你,等我用时间了再处理你这个问题.同步不就反之了,同步信息被立即处理 -- 直到信息处理完成才返回消息句柄;异步信息收到后将在后台处理一段时间 -- 而早在信息处理结束前就返回消息句柄 区别同步和异步 一个进程启动的多个不相干线程,它们相互之间关系为异步。

同步必须执行到底之后才能执行其他操作,而异步可以任意操作 同步的好处与弊端 好处:解决了线程的安全问题。

弊端:每次都有判断锁,降低了效率。

但是在安全与效率之间,首先考虑的是安全。

同步的前提 一、多个线程执行的时候需要同步,如果是单线程则不需要同步。

二、多个线程在执行的过程中是不是使用同一把锁。

如果是,就是同步。

否则不是同步。

synchronzied(obj){ }同一个所 synchronzied(new Object){ } 不是同一个锁 对run()中需要同步的代码进行同步,如果有的32313133353236313431303231363533e78988e69d8331333365653762代码不需要同步,则不要放到同步代码块中去。

同步的表现形式有两种: 1、同步代码块,被同步关键字封装的代码就是同步代码块; 2、同步函数,被同步关键字修饰的函数就是同步函数。

同步代码块的锁是可以是任意对象,在执行之前就好创建好一个锁对象。

那么同步函数的锁在哪里? 同步函数的锁就是调用该同步函数的对象,也就是this。

如果同步函数被static修饰,那么该同步函数的锁就是这个类在堆内存中形成的类文件对象。

这时候不一定有该类的对象,但一定有该类的字节码文件对象。

java用哪种方法实现多线程同步比较好

Java中的同步机制有四种:① ThreadLocal ② synchronized( ) ③ wait() 与 notify() ④ volatile 目的:都是为了解决多线程中的对同一变量的访问冲突 (1)ThreadLocal 保证不同线程拥有不同实例,相同线程一定拥有相同的实例,即为每一个使用该变量的线程提供一个该变量值的副本,每一个线程都可以独立改变自己的副本,而不是与其它线程的副本冲突。

(2)优势:提供了线程安全的共享对象 (3)与其它同步机制的区别:同步机制是为了同步多个线程对相同资源的并发访问,是为了多个线程之间进行通信;而 ThreadLocal 是隔离多个线程的数据共享,从根本上就不在多个线程之间共享资源,这样当然不需要多个线程进行同步了。

(4)使用技巧:需要多个线程之间进行通信,使用同步机制;如果需要隔离多个线程之间的共享冲突,推荐使用 ThreadLocal (线程安全)。

妮妮云80元/月,香港站群云服务器 1核1G

妮妮云的来历妮妮云是 789 陈总 张总 三方共同投资建立的网站 本着“良心 便宜 稳定”的初衷 为小白用户避免被坑妮妮云的市场定位妮妮云主要代理市场稳定速度的云服务器产品,避免新手购买云服务器的时候众多商家不知道如何选择,妮妮云就帮你选择好了产品,无需承担购买风险,不用担心出现被跑路 被诈骗的情况。妮妮云的售后保证妮妮云退款 通过于合作商的友好协商,云服务器提供2天内全额退款,超过2天不退款 物...

RAKsmart 年中活动 独立服务器限时$30秒杀 VPS主机低至$1.99

RAKsmart 虽然是美国主机商,但是商家的主要客户群还是在我们国内,于是我们可以看到每次的国内节日促销活动期间商家也会发布促销。包括这次年中大促活动,RAKsmart商家也有发布为期两个月的年终活动,其中有商家擅长的独立服务器和便宜VPS主机。服务器包括站群服务器、特价服务器、高达10G带宽不限制流量的美国服务器。商家优惠活动,可以看到对应商品的优惠,同时也可以使用 优惠码 RAKBL9 同时...

2021年全新Vultr VPS主机开通云服务器和选择机房教程(附IP不通问题)

昨天有分享到"2021年Vultr新用户福利注册账户赠送50美元"文章,居然还有网友曾经没有注册过他家的账户,薅过他们家的羊毛。通过一阵折腾居然能注册到账户,但是对于如何开通云服务器稍微有点不对劲,对于新人来说确实有点疑惑。因为Vultr采用的是预付费充值方式,会在每月的一号扣费,当然我们账户需要存留余额或者我们采用自动扣费支付模式。把笔记中以前的文章推送给网友查看,他居然告诉我界面不同,看的不对...

多线程同步为你推荐
策略组组策略完全使用方法最开放的浏览器目前最好的游览器?云图片华为手机的云照片怎么不见了怎么办rdl电脑主机上的dvd+rdl是什么意思rdlcordless phone是什么意思oracle索引如何在ORACLE数据库的字段上建立索引bindservice安卓里 remote service到底有什么用李昊天铠甲勇士刑天中人物资料slideshare幻灯片的占位符的作用是?jdk6jdk-6u14-windows-i586.exe是什么,具体点,谢谢
vps论坛 域名服务dns的主要功能为 如何注册中文域名 本网站服务器在美国维护 sharktech 唯品秀 便宜服务器 台湾服务器 webhostingpad 新世界电讯 服务器架设 免费个人网站申请 申请个人网站 免费cdn paypal注册教程 双12 厦门电信 360云服务 域名dns 四川电信商城 更多