在论坛里看到一篇讲线程同步的很好的帖子。http://www.iteye.com/topic/164905
线程同步牢牢记住:1.线程同步就是线程排队。。同步就是排队。线程同步的目的就是避免线程“同步”执行
2“共享”这两个字。只有共享资源的读写访问才需要同步。如果不是共享资源,那么就根本没有同步的必要。
3.只有“变量”才需要同步访问。如果共享的资源是固定不变的,那么就相当于“常量”,线程同时读取常量也不需要同步。至少一个线程修改共享资源,这样的情况下,线程之间就需要同步。
4.多个线程访问共享资源的代码有可能是同一份代码,也有可能是不同的代码;无论是否执行同一份代码,只要这些线程的代码访问同一份可变的共享资源,这些线程之间就需要同步。
为什么需要线程同步?
一个应用程序包含多个线程。每个线程都是独立的,拥有自己的运行栈。 当多个线程同时读写同一份共享资源的时候,可能会引起冲突。这时候,我们需要引入线程“同步”机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团。
怎么样线程同步?
同步锁模型:
就是给共享资源上一把锁。
所谓同步,就是几个需要访问同一个共享资源的不同线程竞争同一把锁。
同步锁本身也一定是多个线程之间的共享对象
任何一个Object Reference都可以作为同步锁。我们可以把Object Reference理解为对象在内存分配系统中的内存地址。因此,要保证同步代码段之间使用的是同一个同步锁,我们就要保证这些同步代码段的 synchronized关键字使用的是同一个Object Reference,同一个内存地址。
同步锁加在什么地方?
把同步锁加在“访问共享资源的代码段”上。而不是共享资源上。
public static final Object lock1 = new Object();
… f1() {
synchronized(lock1){ // lock1 是公用同步锁
// 代码段 A
// 访问共享资源 resource1
// 需要同步
}
同步粒度
线程同步是非常耗费资源的一种操作。我们要尽量控制线程同步的代码段范围。同步的代码段范围越小越好。我们用一个名词“同步粒度”来表示同步代码段的范围。
我们要尽量避免这种直接把synchronized加在函数定义上的偷懒做法。因为我们要控制同步粒度。同步的代码段越小越好。synchronized控制的范围越小越好。
我们不仅要在缩小同步代码段的长度上下功夫,我们同时还要注意细分同步锁。