一个线程同步问题,是多核与多线程造成的吗

用全局变量控制多线程同步是否合适?
[问题点数:20分,结帖人dayong657]
用全局变量控制多线程同步是否合适?
[问题点数:20分,结帖人dayong657]
只显示楼主
取消只显示楼主
匿名用户不能发表回复!|00:30 提问
java多线程操作同一个变量的问题,难道是多核cpu所致?
大家请看代码和输出结果,我百思不得其解,为什么 amount只加了一次,开始我以为是static所致,就算去掉也还是有几率出现这样的结果,难道是多核cpu真的把两个线程同时执行了?
public class MyRunnable implements Runnable {
public static int
public void run() {
// TODO 自动生成的方法存根
String s=Thread.currentThread().getName();
System.out.println(s+"
"+amount);
public class MyFirstThread {
public static void main(String[] args) {
// TODO 自动生成的方法存根
MyRunnable r1=new MyRunnable();
Thread AThread=new Thread(r1);
Thread BThread=new Thread(r1);
AThread.start();
BThread.start();
if((!AThread.isAlive())&&(!BThread.isAlive()))
System.out.println("amount ="+r1.amount);
按赞数排序
没有加同步锁的问题,两个线程是同时执行的,amount什么值都有可能,可能都是1,可能打印都是2,也可能打印2,1。所以需要对amount加同步锁
public static Integer
public void run() {
// TODO 自动生成的方法存根
synchronized(amount){
String s=Thread.currentThread().getName();
System.out.println(s+"
"+amount);
如果只有一个处理器,仍然可能出现线程同步的问题,和什么多cpu同时执行没有关系。
我再说清楚一些
这是因为amount++;不是原子化的操作,它是这样的
x = x + 1;
(这里x代表寄存器,amount代表内存)
我们假设你只有1个cpu,也就是执行本身不是并发的,但是有两个线程
假设amount = 0
此时x = 0, amount=0
切换到线程2
注意,x是寄存器,每个线程独立,而amount是共享的,只有一个,所以为了避免混淆,这里x写成x1表示另一个变量
此时x1=0 amount=0
x1 = x1 + 1;
再切换到线程1
x = x + 1;
再切换到线程2
amount = x1;
记住,x1=1
所以amount=1
结果是1而不是2
为什么这样?因为x存的数据是脏数据,amount被另一个线程更新了,但是x没有更新。
注意,以上代码不是并行执行的,同样有同步问题。
晕,线程没有同步,无论单核多核都需要线程同步。这是起码的常识。
无论单核多核都不是同步执行的,CPU在各个线程随机执行(优先级高的线程得到CPU执行的机会更多),你所看到的同步,其实是CPU在线程之间切换执行,只是速度太快,我们无法跟上。
可以看看龙书的线程同步,讲的十分仔细。
《operating system concepts》
对,单核时代,同一时刻,只有一个执行,现在多核时代了
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐为什么大多数游戏都不做多线程/多核优化?难点是什么? - 知乎653被浏览<strong class="NumberBoard-itemValue" title="7,443分享邀请回答55917 条评论分享收藏感谢收起24521 条评论分享收藏感谢收起C# 关于多线程和CPU的问题_百度知道
C# 关于多线程和CPU的问题
使用1个线程进行操作耗时100秒 为什么使用2个线程和使用20个线程都一样只节省一半时间 照理说20个线程不是应该更省时间吗? 求解...
我有更好的答案
理论上来说你的理解是对的
但是要看软件啊
对多线程优化好的软件 那是相当明显的比如说我用的3DSMAX
它可以运用多线程 并且可以让CPU100%满载运行 那么 i7 有八个线程
4个线程就是我用这个软件就可以提升50%左右
向至强的CPU就更强了
主要是软件 软件可以使用多线程那么提升是相当明显的!
请问一般都是怎么优化的,能举个例子吗?还有下面这段代码,为什么线程数调高了,速度反而更慢&-&-!&
你在百度百科上面 看看多线程 就明白了
上面写的 很详细的!
采纳率:51%
1.CPU发展趋势核心数目依旧会越来越多,依据摩尔定律,由于单个核心性能提升有着严重的瓶颈问题,普通的桌面PC有望在2017年末2018年初达到24核心(或者16核32线程),我们如何来面对这突如其来的核心数目的增加?编程也要与时俱进。笔者斗胆预测,CPU各个核心之间的片内总线将会采用4路组相连:),因为全相连太过复杂,单总线又不够给力。而且应该是非对称多核处理器,可能其中会混杂几个DSP处理器或流处理器。 2.多线程与并行计算的区别(1)多线程的作用不只是用作并行计算,他还有很多很有益的作用。还在单核时代,多线程就有很广泛的应用,这时候多线程大多用于降低阻塞(意思是类似于while(1){if(flag==1)sleep(1);}这样的代码)带来的CPU资源闲置,注意这里没有浪费CPU资源,去掉sleep(1)就是纯浪费了。阻塞在什么时候发生呢?一般是等待IO操作(磁盘,数据库,网络等等)。此时如果单线程,CPU会干转不干实事(与本程序无关的事情都算不干实事,因为执行其他程序对我来说没意义),效率低下(针对这个程序而言),例如一个IO操作要耗时10毫秒,CPU就会被阻塞接近10毫秒,这是何等的浪费啊!要知道CPU是数着纳秒过日子的。所以这种耗时的IO操作就用一个线程Thread去代为执行,创建这个线程的函数(代码)部分不会被IO操作阻塞,继续干这个程序中其他的事情,而不是干等待(或者去执行其他程序)。 同样在这个单核时代,多线程的这个消除阻塞的作用还可以叫做“并发”,这和并行是有着本质的不同的。并发是“伪并行”,看似并行,而实际上还是一个CPU在执行一切事物,只是切换的太快,我们没法察觉罢了。例如基于UI的程序(俗话说就是图形界面),如果你点一个按钮触发的事件需要执行10秒钟,那么这个程序就会假死,因为程序在忙着执行,没空搭理用户的其他操作;而如果你把这个按钮触发的函数赋给一个线程,然后启动线程去执行,那么程序就不会假死,继续相应用户的其他操作。但是,随之而来的就是线程的互斥和同步、死锁等问题,详细见有关文献。现在是多核时代了,这种线程的互斥和同步问题是更加严峻的,单核时代大都算并发,多核时代真的就大为不同,为什么呢?具体细节请参考有关文献。我这里简单解释一下,以前volatile型变量的使用可以解决大部分问题,例如多个线程共同访问一个Flag标志位,如果是单核并发,基本不会出问题(P.S.在什么情况下会出问题呢?Flag有多个,或者是一个数组,这时候只能通过逻辑手段搞定这个问题了,多来几次空转无所谓,别出致命问题就行),因为CPU只有一个,同时访问这个标志位的只能有一个线程,而多核情况下就不太一样了,所以仅仅volatile不太能解决问题,这就要用到具体语言,具体环境中的“信号量”了,Mutex,Monitor,Lock等等,这些类都操作了硬件上的“关中断”,达到“原语”效果,对临界区的访问不被打断的效果,具体就不解释了,读者可以看看《现代操作系统》。(2)并行计算还可以通过其他手段来获得,而多线程只是其中之一。其他手段包括:多进程(这又包括共享存储区的和分布式多机,以及混合式的),指令级并行。ILP(指令级并行),x86架构里叫SMT(同时多线程),在MIPS架构里与之对应的是super scalar(超标量)和乱序执行,二者有区别,但共同点都是可以达到指令级并行,这是用户没法控制的,不属于编程范围,只能做些有限的优化,而这有限的优化可能只属于编译器管辖的范畴,用户能做的甚少。(3)典型的适于并行计算的语言Erlang和MPI:这两个前者是语言,后者是C++和Fortran的扩展库,效果是一样的,利用多进程实现并行计算,Erlang是共享存储区的,MPI是混合型的。C#.NET4.0:新版本4.0可以用少量代码实现并行For循环,之前版本需要用很繁琐的代码才能实现同样功能。这是利用了多线程实现并行计算。Java和C#3.5都有线程池(ThreadPool),也是不错的很好用的多线程管理类,可以方便高效的使用多线程。CUDA,还是个初生牛犊,有很大的发展潜力,只不过就目前其应用领域很有限。其目前只能使用C语言,而且还不是C99,比较低级,不能使用函数指针。个人感觉这由于硬件上天生的局限性(平均每个核心可用内存小,与系统内存通讯时间长),只适用于做科学计算,静态图像处理,视频编码解码,其他领域,还不如高端CPU。等以后GPU有操作系统了,能充分调度GPU资源了,GPU就可以当大神了。游戏中的物理加速,实际上多核CPU也能很好的做到。
线程中间有个sleep方法。 程序中有死循环而且中间没用sleep所有导致的。循环一次一定要sleep一下。要不他一直占住CPU不释放,导致程序死锁。在线程里面加上 :System.Threading.Thread.Sleep(10000);就能解决这个问题了。
为您推荐:
其他类似问题
您可能关注的内容
多线程的相关知识
&#xe675;换一换
回答问题,赢新手礼包&#xe6b9;
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。Linux/Nginx/Apache/PHP/MySQL/C/JAVA/Python/Perl/关系型数据库/Memcached/Redis/MongoDB/Tokyo Tyrant/NoSQL/Sphinx/Solr/Lucene/ElasticSearch/搜索引擎/面向对象/设计模式/数据结构/算法/架构/分布式/高性能/高可用/高并发/高可扩展性/文件系统/开源/大数据/数据挖掘
岂能尽如人意,但求无愧我心; 努力不一定会成功,但是放弃一定会失败; 态度决定一切,责任心、细心、上进心; 认认真真做事,踏踏实实做人; 今天工作不努力,明天努力找工作; 好好学习,天天向上,不求与人相比,但求超越自己; 知其然,还要知其所以然; 天道酬勤; 好记忆不如烂笔头,有好的心得 、想法、工作及学习中遇到的问题一定要及时记录下来,防止以后忘记;
此文中的大部分资料来自于网络上,我只是觉得把有道理的整理一下,方便以后查阅。
1.多线程在单核和多核CPU上的执行效率问题的讨论a1: 多线程在单cpu中其实也是顺序执行的,不过系统可以帮你切换那个执行而已,其实并没有快(反而慢)多个cpu的话就可以在两个cpu中同时执行了..............
a2: 单核CPU上运行的多线程程序, 同一时间只能一个线程在跑, 系统帮你切换线程而已, 系统给每个线程分配时间片来执行, 每个时间片大概10ms左右, 看起来像是同时跑, 但实际上是每个线程跑一点点就换到其它线程继续跑
效率不会有提高的切换线程反倒会增加开销
a3: #3楼说的是对的。所以一般没有必要的话,尤其在单核CPU的时候,不推荐使用多线程。单核CPU时使用多线程,通常是有线程要处于等待状态。而对于普通的进度条更新类的,能够简单控制的(比如:在循环里面手动处理消息)就简单控制,一般不使用线程,这样可以提高程序的性能。并且避免掉不必要的线程同步问题。
a4: 你试一下双核三线程,保准效率反而比双线程低!
算法同样时,CPU占用率达到100%的最小线程数效率最高,如果是cpu占率率高的运算单核单线程,双核双线程,四核四线程是最适合的。
但为什么有时候线程数超过CPU内核数会更快呢?原因是这种程序的单个线程运算量不足以占满CPU一个内核(比如存在大量IO操作,IO比较慢,是程序瓶颈)。
a5: 多线程的用处在于,做某个耗时的操作时,需要等待返回结果,这时用多线程可以提高程序并发程度。如果一个不需要任何等待并且顺序执行能够完成的任务,用多线程简直是浪费。
2.浅谈多核CPU、多线程与并行计算
a1: CPU发展趋势
核心数目依旧会越来越多,依据摩尔定律,由于单个核心性能提升有着严重的瓶颈问题,普通的桌面PC有望在2017年末2018年初达到24核心(或者16核32线程),我们如何来面对这突如其来的核心数目的增加?编程也要与时俱进。笔者斗胆预测,CPU各个核心之间的片内总线将会采用4路组相连:),因为全相连太过复杂,单总线又不够给力。而且应该是非对称多核处理器,可能其中会混杂几个DSP处理器或流处理器。
a2: 线程越多越好吗?什么时候才有必要用多线程?
线程必然不是越多越好,线程切换也是要开销的,当你增加一个线程的时候,增加的额外开销要小于该线程能够消除的阻塞时间,这才叫物有所值。
Linux自从2.6内核开始,就会把不同的线程交给不同的核心去处理。Windows也从NT.4.0开始支持这一特性。
什么时候该使用多线程呢?这要分四种情况讨论:
a.多核CPU&&计算密集型任务。此时要尽量使用多线程,可以提高任务执行效率,例如加密解密,数据压缩解压缩(视频、音频、普通数据),否则只能使一个核心满载,而其他核心闲置。
b.单核CPU&&计算密集型任务。此时的任务已经把CPU资源100%消耗了,就没必要也不可能使用多线程来提高计算效率了;相反,如果要做人机交互,最好还是要用多线程,避免用户没法对计算机进行操作。
c.单核CPU&&IO密集型任务,使用多线程还是为了人机交互方便,
d.多核CPU&&IO密集型任务,这就更不用说了,跟单核时候原因一样。
4.程序员需要掌握的技巧/技术
(1)减少串行化的代码用以提高效率。这是废话。
(2)单一的共享数据分布化:把一个数据复制很多份,让不同线程可以同时访问。
(3)负载均衡,分为静态的和动态的两种。具体的参见有关文献。
3.请问:CPU的多核和应用程序的多线程的关系是怎么样的?a1: 多核儿就是系统同时可以运行多个线程,比如双核可以同时执行两个线程。单核儿只能一次执行一个线程。
a2: 试了一个ping 从192.168.0.1 到192.169.0.255的程序用多线程做的,发现在单核的机器上和多核的机器运行性能有两倍左右的差异。
a3: 多核对于用户,应该说对于程序员来说,是透明的,根本不用管它,当你是单核的编程就可以了,除非使用OpenMP进行编程,就用很多条条框框了,另外你上面的测试是不准确的,网络(主要是远程主机)会因为不同时候而有不同的响应速度,你应该在干净的本机同环境下进行测试.但是,对于多线程多核优于单核还是可以确定的. 总之,我们不用担心程序在单核或多核上会出现并发问题.
a4: 多核指的是CPU有多个核心,多线程是程序有多个线程在同时执行。多核也要用多线程才能发挥优势。同样,多线程要在多核上才能真正有优势。这点来说,对程序员不是透明的。程序员可以控制程序/线程在哪个CPU(核)上运行。用户也可以控制程序在哪几个核上运行。所以多核,多线程对用户和程序员都不是透明的。程序员必须了解这方面的知识。才能让程序最大限度的发挥机器的性能。
4.pthreadphp手册中关于pthread有关函数: pthread扩展:
延伸阅读:[转]浅谈多核CPU、多线程与并行计算: PHP使用Pthread实现的多线程操作实例: php三种实现多线程类似的方法:
阅读(...) 评论()

我要回帖

更多关于 多核多线程 的文章

 

随机推荐