synchronized同步锁
来源:互联网 发布:系统工程编程 编辑:程序博客网 时间:2024/06/09 19:23
synchronized简介
synchronized是Java中的关键字,是一种同步锁。它可以修饰以下对象
1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
synchronized使用注意事项
1.多个对象就有多个同步锁
synchronized获取的都是对象锁,而不是把一段代码和方法当成锁。看看下面的例子
class MyObject{ private String passWord = "a"; private String userName = "b"; synchronized public void setValue(String p, String u){ this.passWord = p; try{ Thread.sleep(100); }catch(InterruptedException e){ } this.userName = u; System.out.println(Thread.currentThread().getName() + " passWord :" + passWord); System.out.println(Thread.currentThread().getName() + " userName :" + userName); }}public class Thread_test { public static void main (String[] args){ MyObject obj1 = new MyObject(); MyObject obj2 = new MyObject(); Thread thread1 = new Thread(){ @Override public void run(){ System.out.println("线程1 开始运行"); obj1.setValue("aa","bb"); } }; Thread thread2 = new Thread(){ @Override public void run(){ System.out.println("线程2 开始运行"); obj2.setValue("cc","dd"); } }; thread1.setName("线程1"); thread1.start(); thread2.setName("线程2"); thread2.start(); }}
在上面的例子中实例化了2个MyObject对象obj1和obj2,然后别在线程1和2用调用obj1和obj2的方法setValue,可以看到程序的执行顺序和结果,他们没有受synchronized的影响,各自在自己空间运行。
2.如果线程A持有 object 对象的synchronized同步锁,这时如果线程B要调用object对象中具有synchronized修饰的方法,则需要等待线程A释放后才能执行(不管线程A和B调用的是否是同一个方法,只要是被synchronized 修饰,线程B都必须等待)。实例如下:
class MyObject{ private String passWord = "a"; private String userName = "b"; synchronized public void setPassWord(String p){ this.passWord = p; try{ Thread.sleep(1000); }catch(InterruptedException e){ } System.out.println(Thread.currentThread().getName() + " 执行完成 " + " passWord :" + passWord); } synchronized public void setUserName(String u){ this.userName = u; System.out.println(Thread.currentThread().getName() + " 执行完成 " + " userName :" + userName); }}public class Thread_test { public static void main (String[] args){ MyObject obj1 = new MyObject(); Thread thread1 = new Thread(){ @Override public void run(){ System.out.println("线程1 开始运行"); obj1.setPassWord("aa"); } }; Thread thread2 = new Thread(){ @Override public void run(){ System.out.println("线程2 开始运行"); obj1.setUserName("dd"); } }; thread1.setName("线程1"); thread1.start(); thread2.setName("线程2"); thread2.start(); }}
可以看到在上面的例子中线程1先执行,紧接着线程2执行。但在线程1执行的方法setPassWord中休眠1秒,由于线程1获取同步锁,所以线程2要等到线程1释放了锁后,线程2才能调用setUserName函数。虽然线程1没有调用方法setUserName,但是setUserName是被synchronized修饰,所以仍然要同步。如果我们将函数setUserName前面的synchronized去掉看看执行的结果又是啥
我们看到线程2先执行完全。这说明线程A持有 object 对象的synchronized同步锁,这时如果线程B可以调用object对象中具有非synchronized修饰的方法,而不需等待线程A释放同步锁。
3.synchronized同步锁不能继承
class MyObject{ private String passWord = "a"; private String userName = "b"; synchronized public void setValue(String p, String u){ System.out.println("线程 " + Thread.currentThread().getName() + "父类 MyObject" + " setValue 开始运行"); this.passWord = p; this.userName = u; System.out.println("线程 " + Thread.currentThread().getName() + "父类 MyObject" + " passWord :" + passWord); System.out.println("线程 " + Thread.currentThread().getName() + "父类 MyObject" + " userName :" + userName); try{ Thread.sleep(2000); }catch(InterruptedException e){ } System.out.println("线程 " + Thread.currentThread().getName() + "父类 MyObject" + " setValue 运行结束"); }}class MyObject1 extends MyObject{ private String passWord = "a"; private String userName = "b"; public void setValue(String p, String u){ System.out.println("线程 " + Thread.currentThread().getName() + "子类 MyObject" + " setValue 开始运行"); this.passWord = p; this.userName = u; System.out.println("线程 " + Thread.currentThread().getName() + "子类 MyObject1" + " passWord :" + passWord); System.out.println("线程 " + Thread.currentThread().getName() + "子类 MyObject1" + " userName :" + userName); super.setValue(p, u); System.out.println("线程 " + Thread.currentThread().getName() + "子类 MyObject" + " setValue 运行结束"); }}public class Thread_test { public static void main (String[] args){ try{ MyObject1 obj1 = new MyObject1(); Thread thread1 = new Thread(){ @Override public void run(){ obj1.setValue("11","22"); } }; thread1.setName("a"); thread1.start(); Thread.sleep(10); Thread thread2 = new Thread(){ @Override public void run(){ obj1.setValue("33", "44"); } }; thread2.setName("b"); thread2.start(); }catch(InterruptedException e){ } }}
上面的例子MyObject1继承于MyObject并重写了函数setValue,MyObject1的函数setValue没有添加同步锁,MyObject的的函数setValue添加了同步锁,我们还在MyObject1的函数setValue里面调用了父类的setValue函数。看看上面两个线程的执行结果, MyObject1的函数setValue没有添加同步锁,所以线程1,2可以各自执行,同时运行(不用等到线程1执行完成,线程2才开始执行),但是由于MyObject的的函数setValue添加了同步锁,所以MyObject1在调用父类的setValue函数时必须同步,也就是线程1运行完成了,线程2才能开始运行。
4.synchronized修饰代码块之间的同步问题
A.synchronized(this)
当一个线程访问object的一个synchronized(this)的同步代码块时,其他线程对同一个object中所有其他synchronized(this)同步代码快将 被阻塞。
B. .synchronized(非this对象 x)
当一个线程访问object的一个synchronized(X)的同步代码块时,其他线程对同一个object中所有其他synchronized(X)同步代码快将 被阻塞。但是synchronized(y),synchronized(z)修饰的代码块被阻塞
5.synchronized修饰静态函数
A. 与修饰非静态方法的区别
synchronized关键字添加到static方法上是给Class类添加锁,而synchronized添加到非static方法上是给对象加锁
B.synchronized静态函数同步情况
当一个线程访问synchronized静态函数,其他线程可以对该类的其他synchronized静态函数反问,而不会被阻塞。
6.synchronized(object.class)修饰代码块
当一个线程访问synchronized(object.class)代码块时,其他任何线程访问该代码块时都会被阻塞。
- synchronized同步锁详解
- java 同步锁(synchronized)
- synchronized 同步锁
- synchronized同步锁详解
- synchronized 同步锁
- synchronized线程同步锁
- java同步锁(synchronized)
- java 同步锁(synchronized)
- synchronized同步锁
- Java synchronized同步锁
- java 同步锁(synchronized)
- synchronized同步锁
- java-同步锁synchronized
- java 同步锁(synchronized)
- synchronized同步锁
- 同步锁synchronized
- java 同步锁(synchronized)
- java 同步锁(synchronized)
- 19.Struts2_表单标签
- 洛谷 2737 麦香牛块 最短路SPFA? 解题报告
- HTML5图片与文本对齐方式
- Java 基本数据类型
- Hive基本操作笔记
- synchronized同步锁
- 凸凸凸的eclipse快捷键与壁纸
- Hive分区表新增字段为null的bug及解决方法
- Phalcon 上传文件
- 使用APACHE KNOX作为proxy访问web,同时开启SSO功能
- 2014年蓝桥杯之切面条
- SQL创建表之数据类型;
- Netd测试工具ndc
- CodeForces 327D(DFS)