近在读《深入理解并行编程》,是C的,前面的200页感觉是通用的思想,前面提到有一个计数器的问题,于是就自己想着用java来实现下.
中间有遇到问题:
1.假设只有两个线程,一读一写,是否需要给这个资源加锁?
2.线程状态的改变
先上代码再说吧:
public class Test { private int counts = 0;// 这个是统计总数 private int inci_1 = 0;// 这个是线程1的变量 private int inci_2 = 0;// 这个是线程2的变量 private int inci_3 = 0;// 这个是线程3的变量 private boolean a = false, b = false, c = false; /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Test t = new Test(); Inc1 inc1 = t.new Inc1(); Inc2 inc2 = t.new Inc2(); Inc3 inc3 = t.new Inc3(); CountAll c = t.new CountAll(); Thread t1 = new Thread(inc1); Thread t2 = new Thread(inc2); Thread t3 = new Thread(inc3); Thread ct = new Thread(c); t1.start(); t2.start(); t3.start(); ct.start(); } //线程1 class Inc1 implements Runnable { public void run() { for (int i = 0; i < 300000000; i++) { inci_1++; } a = true; } } //线程2 class Inc2 implements Runnable { public void run() { for (int i = 0; i < 300000000; i++) { inci_2++; } b = true; } } //线程3 class Inc3 implements Runnable { public void run() { for (int i = 0; i < 300000000; i++) { inci_3++; } c = true; } } //统计器 class CountAll implements Runnable { @Override public void run() { // TODO Auto-generated method stub while (!(a && b&&c)) { counts = inci_1 + inci_2 + inci_3; System.out.println(counts); } counts = inci_1 + inci_2 + inci_3; System.out.println("最后的结果是: "+counts); } } }
那么,解决问题的时刻来了:挖掘机技术到底哪家强?????? (扯一下而已,大家不要介意,请自动忽略,只是为了显示LZ是个DB)
中间的想法是:给每一个线程分配到一个空间,线程之间不会相互影响,只需要通过一个统计器来更新所有的工作就好了.关键在于一点,没有了锁.
《深入理解并行编程》中是这样描述的:
如果一个线程去操作一个加锁的变量,必须先把这个变量加载进CPU,再修改.这个时候若是还有另一个线程进行操作,那线程1需要把东西通过CPU的System Interconnect发送到线程2,线程1进行擦除操作.然后线程2再进行修改.也就是说:这个多线程效率还不如单线程高
那就回来了,我们为什么还需要去加锁解锁?
另外,这个线程间的状态的办法是自己想出来的,因为公司电脑没鼠标,不能上网(新员工),只能撸这么多,等拷回家再发.
1.合法的并行线程会大量增加程序的状态空间,导致程序难以理解,降低生产率
2.假设我有10000条东西要弄,有100个线程,那么我需要给线程每个分配100的量就好,这样既兼顾了效率也兼顾了资源
3.编写并行软件最重要的考虑是如何进行分割正确的分割问题能够让解决办法简单,可扩展并且高性能,而不恰当的分割问题则会产生缓慢且复杂的解决方案.
4.在锁竞争必须降低和同步开销不是主要局限时,可以使用数据锁---数据锁是通过将一块过大的临界区分散到各个小的临界区来减少锁的竞争.不过这种扩展性的增强带来的是复杂性的提高,增加了额外的数据结构.
记录下来,以备查验