首先,楼主要明白使用并发(线程)会出现的问题。
第一:合作同步
合作同步可以用简单的生产者和消费者的问题来说明,一个程序单元生成某个数据值或者某项资源另一个程序要使用,
生成的数据通常由生产单元放在存储缓冲区中,由消费单元从缓冲区中移除。向缓冲区中移除的顺序必须同步。如果缓冲区是空的,消费单元就不允许
从缓冲区中取数据。同样的当缓冲区满时,生产单元不允许往缓冲区存放新的数据,这就是合作同步的问题。
解决办法:可以使用wait(),notify()和notifyAll()方法实现,所有这些方法都在都在根类Object中定义,出了Object以外的所有类都继承了这些方法。
用notify()方法可以告诉某个等待中的线程,它所等待的事件已经发生,无法确定是哪一个线程被notify()唤醒,因为虚拟机随机从线程对象的等待列表
中选择一个线程。所以通常使用notifyAll()方法唤醒对象等待列表中的所有线程,在他们调用wait()后立即开始执行。
wait(),notify(),notifyAll()方法可以只在同步方法中调用,因为他们使用了由同步方法放置在对象上的锁。而对wait()的调一般是放在while()中,由方法
等待的条件来控制。
第二:竞争同步
这里假设现在有一个为num的int的共享数据,它的初始值是3,现在有两个线程要对其进行运算,A线程要对其进行+1,而B线程要对其*2,
假如他们没有竞争同步,根据他们的顺序,这些操作就可能导致4种不同的结果。
①如果A在B获取num之前完成num运算,那么最后的值是8
②如果A在运算之前获取num时,B也获取了num值,那么就可能导致另外2种的值
1,假如A比B先完成运算,那么值是6。(A把值+1,num=4,而B进行*3运算完后,把A运算出来的值覆盖了,num=6)
2,假如A比B后完成运算,那么值是4。(B把值*3,num=6,而A把值进行+1,完后把B算出来的值覆盖了,num=4)
③如果B在A获取num值之前完成运算,num的值将是7。
因为两个或者更多的任务竞争使用共享支援,程序的表现取决于哪一个任务先到达,竞争同步的重要性现在就应该很清楚了
解决办法:我们可以用一个锁来解决此类的问题,两个或更多的方法被同一个锁锁住并且持共同的钥匙,他们谁持有钥匙那么其它在持有钥匙
的线程执行完之前不能进入被锁住的内容,synchronized的作用就体现出来了。
格式:
synchronized(表达式){
语句
}
其中,表达式必须对一个对象求值,语句可以是单条语句或者是复合语句。对象在语句或或复合语句执行时被枷锁。
定义有同步方法的对象必须有一个相关联的队列,当同步方法操作时,将其他试图执行它的同步方法储存起来,这队列是隐式提供的。
当同步方法完成了在对象上的执行,那么在对象等待队列中等待的方法(如果有的话)就被放入任务的就绪队列
|