synchronized 方法与锁对象
2016-03-15 23:16
274 查看
两个线程均调用共享对象的同步方法:
结果肯定是顺序执行:
A线程调用共享对象的同步方法,B线程调用共享对象非同步方法:
结果是:
A线程调用共享对象的同步方法,B线程调用共享对象另一个同步方法
结果是:
结论:
1. A线程和B线程均调用object对象的synchronized方法,则必须是同步方式调用
2. A线程先持有object对象的Lock锁,B线程可以以异步方式调用object对象中的非synchronized类型的方法
3. A线程先持有object对象的Lock锁,B线程如果此时调用object对象中的synchronized类型的方法则需等待,即只能是同步方式调用
结论2即对应了脏读的现象:
比如赋值方法是同步,取值方法是非同步,则可能出现脏读,即在读取实例变量时,此值已经被其他线程更改过了
可对getValue添加synchronzied关键字修饰,避免脏读
当线程调用anyObject对象加入synchronized关键字修饰的X方法时,A线程就获得了X方法锁,更准确的讲是获得了anyObject对象的锁,所以其他线程必须等A线程执行完毕才可以调用X方法,但是其他线程可以调用anyObject的其他非synchronized关键字修饰的方法。可若其他线程调用anyOjbect的其他synchronized关键字修饰的方法时,也必须等待A线程执行完毕,释放了对象锁后才可以调用
class MyObject{ public synchronized void methodA(){ System.out.println("begin methodA threadName= " + Thread.currentThread().getName()); try { Thread.sleep(5000); System.out.println("methodA end"); } catch (InterruptedException e) { e.printStackTrace(); } } } class ThreadA extends Thread{ private MyObject object; public ThreadA(MyObject object){ this.object = object; } @Override public void run() { object.methodA(); } } class ThreadB extends Thread{ private MyObject object; public ThreadB(MyObject object){ this.object = object; } @Override public void run() { object.methodA(); } } public class Run { public static void main(String[] args) { MyObject object = new MyObject(); ThreadA a = new ThreadA(object); a.setName("A"); ThreadB b = new ThreadB(object); b.setName("B"); a.start(); b.start(); } }
结果肯定是顺序执行:
begin methodA threadName= A methodA end begin methodA threadName= B methodA end
A线程调用共享对象的同步方法,B线程调用共享对象非同步方法:
class MyObject{ public synchronized void methodA(){ System.out.println("begin methodA threadName= " + Thread.currentThread().getName()); try { Thread.sleep(5000); System.out.println("methodA end"); } catch (InterruptedException e) { e.printStackTrace(); } } public void methodB(){ System.out.println("begin methodB threadName= " + Thread.currentThread().getName()); try { Thread.sleep(5000); System.out.println("methodB end"); } catch (InterruptedException e) { e.printStackTrace(); } } } class ThreadA extends Thread{ private MyObject object; public ThreadA(MyObject object){ this.object = object; } @Override public void run() { object.methodA(); } } class ThreadB extends Thread{ private MyObject object; public ThreadB(MyObject object){ this.object = object; } @Override public void run() { object.methodB(); } } public class Run { public static void main(String[] args) { MyObject object = new MyObject(); ThreadA a = new ThreadA(object); a.setName("A"); ThreadB b = new ThreadB(object); b.setName("B"); a.start(); b.start(); } }
结果是:
begin methodA threadName= A begin methodB threadName= B methodA end methodB end
A线程调用共享对象的同步方法,B线程调用共享对象另一个同步方法
class MyObject{ public synchronized void methodA(){ System.out.println("begin methodA threadName= " + Thread.currentThread().getName()); try { Thread.sleep(5000); System.out.println("methodA end"); } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void methodB(){ System.out.println("begin methodB threadName= " + Thread.currentThread().getName()); try { Thread.sleep(5000); System.out.println("methodB end"); } catch (InterruptedException e) { e.printStackTrace(); } } } class ThreadA extends Thread{ private MyObject object; public ThreadA(MyObject object){ this.object = object; } @Override public void run() { object.methodA(); } } class ThreadB extends Thread{ private MyObject object; public ThreadB(MyObject object){ this.object = object; } @Override public void run() { object.methodB(); } } public class Run { public static void main(String[] args) { MyObject object = new MyObject(); ThreadA a = new ThreadA(object); a.setName("A"); ThreadB b = new ThreadB(object); b.setName("B"); a.start(); b.start(); } }
结果是:
begin methodA threadName= A methodA end begin methodB threadName= B methodB end
结论:
1. A线程和B线程均调用object对象的synchronized方法,则必须是同步方式调用
2. A线程先持有object对象的Lock锁,B线程可以以异步方式调用object对象中的非synchronized类型的方法
3. A线程先持有object对象的Lock锁,B线程如果此时调用object对象中的synchronized类型的方法则需等待,即只能是同步方式调用
结论2即对应了脏读的现象:
比如赋值方法是同步,取值方法是非同步,则可能出现脏读,即在读取实例变量时,此值已经被其他线程更改过了
class MyObject{ private String username = "A"; private String password = "AA"; public synchronized void setValue(String username, String password){ this.username = username; try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } this.password = password; System.out.println("setValue username : " + username + " password : " + password); } public void getValue(){ System.out.println("getValue username : " + username + " password : " + password); } } class ThreadA extends Thread{ private MyObject object; public ThreadA(MyObject object){ this.object = object; } @Override public void run() { object.setValue("B", "BB"); } } public class Run { public static void main(String[] args) { MyObject object = new MyObject(); ThreadA a = new ThreadA(object); a.setName("A"); a.start(); try { Thread.sleep(200);//结果受此值影响 } catch (InterruptedException e) { e.printStackTrace(); } object.getValue(); } }
可对getValue添加synchronzied关键字修饰,避免脏读
当线程调用anyObject对象加入synchronized关键字修饰的X方法时,A线程就获得了X方法锁,更准确的讲是获得了anyObject对象的锁,所以其他线程必须等A线程执行完毕才可以调用X方法,但是其他线程可以调用anyObject的其他非synchronized关键字修饰的方法。可若其他线程调用anyOjbect的其他synchronized关键字修饰的方法时,也必须等待A线程执行完毕,释放了对象锁后才可以调用
相关文章推荐
- 20 个 CSS 高级技巧汇总
- python学习之常用的内置类(4):python中的XML
- Android 防内存泄露handler
- poj 1804 Brainman(归并排序求逆序对)
- 经典算法练习
- /* 判断一个对象是不是数组*/
- 【Android开发】greenrobot三大开源利器详解(一)——EventBus
- Leetcode #12 & #13 Integer to Roman & Roman to Integer 解题小节
- LINQ查收数据库的性能瓶颈
- 前端调试
- hadoop 2.7.2开发环境配置
- Linux命令对应的全称解释
- hdu——1106排序(重定向)
- 项目4:百钱买百鸡
- 绘制模拟Android钟 ####时钟表盘
- 04+罗潇潇+罗潇第三次作业
- leetcode 45. Jump Game II
- markdown简介及语法
- hadoop1.2备忘录
- 如何解决Eclipse开发android程序的编译错误:com/android/dx/command/dexer/Main : Unsupported major.minor version 52.0?