【多线程】线程中的同步锁synchronized
2016-07-25 21:23
232 查看
当多个线程同时执行时,由于cpu是随机分片的,所以,一个线程在执行过程中被另一个线程打断的情况是经常发生的。 这在某些情况下是会影响到正常的程序的输出结果的。比如银行转账一个人的账户在转账时是不能允许同时有另外一个线程也在执行的。 这就是线程同步要解决的问题。 通常发生在存在共享数据的时候。如果没有共享数据,就不会出现加锁的问题。
线程不同步问题引入
public class TestSync implements Runnable{ Timer timer=new Timer();//都是同一个对象 public static void main(String[] args){ TestSync test=new TestSync(); Thread t1=new Thread(test); Thread t2=new Thread(test); t1.setName("t1"); t2.setName("2"); t1.start(); t2.start(); } public void run(){ timer.add(Thread.currentThread().getName()); } } class Timer{ private static int num=0; public void add(String name){ num++; try{ //这里的sleep只是放大了效果,如果没有sleep,这种被打断也是存在的。 Thread.sleep(1);//1睡眠,2去执行 }catch(InterruptedException e){ return; } System.out.println(name+"你是第"+num+"个使用timer的线程"); } }
执行上面的小程序,我们发现执行的结果是: thread-0你是第2个使用timer的线程 thread-1你是第2个使用timer的线程 分析其原因:是在执行第一个线程的过程中,当执行到num++时,这个时候num=1,但是还没打印出结果时,cpu就去执行第二个线程了, 这个时候又执行了num++这个时候num=2了,同时cpu又去执行第一个线程开始打印结果,然后再去打印第二个线程的结果,就出现上述这种情况了。 那么,为了解决这种问题,我们就需要用线程同步的思想,让线程1完全执行完以后,再去执行线程2。因为两个线程之间存在共享变量。 所以不能允许两个线程同时操作一个变量。
synchronized
其中一种解决上述问题的就是通过synchronized同步锁来实现线程同步。
class Timer{ private static int num=0; public synchronized void add(String name){ //synchronized(this){ num++; try{ Thread.sleep(1); }catch(InterruptedException e){ return; } System.out.println(name+"你是第"+num+"个使用timer的线程"); //} } }
可以实现同步块的方式,也可以使用同步方法的方式。在这里都是可以的。
synchronized个人理解:
同步锁,就好像拥有一个房间的一把锁一样,只有你拿到这把锁的钥匙,那么你才能进入这个房间。 同步锁可分为很多级别的,类级别的,方法级别的和代码块级别的。 其中方法级别和代码块级别的加锁都是针对访问的对象内部加锁的。如果一个对象的某一个方法加锁了, 那么这个对象还是可以访问其他没有加锁的方法或者属性的。而其他对象(新new出来的对象)仍然可以同时访问当前这个加锁的方法。 当然这样的话,线程之间的对象就不是共享的了。 而类级别的锁,是针对于同一个类不同的访问对象。这样只要一个实例对象拥有了这个类的锁,那么其他实例对象是不能拥有这个类的锁的。 以上是我对synchronized这个同步锁的理解。
相关文章推荐
- editText设置背景后,被软键盘覆盖
- java图像处理-(指定区域内)灰度化、透明化(alpha通道)处理
- RunLoop详解4
- 2.使用树梅派进行视频录制
- CodeForces 289B Polo the Penguin and Matrix (数学,中位数)
- 个人主页
- CSS预处理技术总结(一)Less
- 利用XShell上传、下载文件(使用sz与rz命令),超实用!
- Rails(栈)
- python 学习(五) While 循环语句
- 我的Android进阶之旅------>解决Error:Unable to find method 'org.gradle.api.internal.project.ProjectInternal.g
- <实训|第六天>偷偷让新手的Linux无限重启附linux主机名称不是随便乱改的!
- iOS runloop 创建一个和App生命周期相同的线程
- 选择排序
- 欢迎使用CSDN-markdown编辑器
- JAVA之多线程入门和自动滚轮
- POJ1328贪心算法
- poj 2586 Y2K Accounting Bug
- 看病要排队
- Perl学习笔记(3)----遍历哈希表的一个容易疏忽的地方