记录代码
有兴趣可以运行试试,然后想想。
最终结论只有一条:
该synchronized修饰的方法的持有对象(同步方法)
该synchronized修饰的对象(同步块)
目前我所知的synchronized关键字用法,分3种情况:
?
/** * 关于同步关键字 “synchronized” 的学习,思考 */ package sync; import java.util.ArrayList; import java.util.List; /** * @author lyjilu 2012-2-26 * @version 1.0 * Copyright (c) 2011-2012, lyjilu. All rights reserved. */ public class First implements Sync{ static List<String> list = new ArrayList<String>(); /** * 如果不注意编码规范。 * 此方法里做的操作真的是同步,安全的吗? * 看看几种情况下,list的值. * @throws InterruptedException */ public synchronized void a() throws InterruptedException { System.out.println(System.currentTimeMillis() + "我是A开始====="); list.add("a1"); Thread.sleep(1000); System.out.println(list); list.add("a2"); System.out.println(System.currentTimeMillis() + "我是A结束====="); } public synchronized void b() throws InterruptedException { System.out.println(System.currentTimeMillis() + "我是A开始====="); list.add("a1"); Thread.sleep(1000); System.out.println(list); list.add("a2"); System.out.println(System.currentTimeMillis() + "我是A结束====="); } /** * * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { //第一种情况:不同对象访问那个同步方法 // First.t1(); //第二种情况:同一对象访问那个同步方法 // First.t2(); //第三种情况:同一对象访问该对象不同同步方法 First.t3(); } /** * 不同对象访问那个同步方法 * @throws InterruptedException */ public static void t1() throws InterruptedException{ First f1 = new First(); First f2 = new First(); FirstT1 tt = new FirstT1(f1); FirstT2 tt2 = new FirstT2(f2); new Thread(tt).start(); Thread.sleep(100); new Thread(tt2).start(); } /** * 同一对象访问那个同步方法 * @throws InterruptedException */ public static void t2() throws InterruptedException{ First f1 = new First(); FirstT1 tt = new FirstT1(f1); FirstT2 tt2 = new FirstT2(f1); new Thread(tt).start(); Thread.sleep(100); new Thread(tt2).start(); } /** * 同一对象访问该对象的不同同步方法 * @throws InterruptedException */ public static void t3() throws InterruptedException{ First f1 = new First(); FirstT1 tt = new FirstT1(f1); FirstT3 tt3 = new FirstT3(f1); new Thread(tt).start(); Thread.sleep(100); new Thread(tt3).start(); } } class FirstT1 implements Runnable { First t; public FirstT1(First test) { t = test; } public void run() { try { t.a(); } catch (InterruptedException e) { e.printStackTrace(); } } } class FirstT2 implements Runnable { First t; public FirstT2(First test) { t = test; } public void run() { try { t.a(); } catch (InterruptedException e) { e.printStackTrace(); } } } class FirstT3 implements Runnable { First t; public FirstT3(First test) { t = test; } public void run() { try { t.b(); } catch (InterruptedException e) { e.printStackTrace(); } } }? 第二种情况:
/** * 关于同步关键字 “synchronized” 的学习,思考 */ package sync; import java.util.ArrayList; import java.util.List; /** * * @author lyjilu 2012-2-26 * @version 1.0 * Copyright (c) 2011-2012, lyjilu. All rights reserved. */ public class Second implements Sync{ static List<String> list = new ArrayList<String>(); public synchronized static void a() throws InterruptedException { System.out.println(System.currentTimeMillis() + "我是A开始====="); list.add("a1"); Thread.sleep(1000); System.out.println(list); list.add("a2"); System.out.println(System.currentTimeMillis() + "我是A结束====="); } public synchronized static void b() throws InterruptedException { System.out.println(System.currentTimeMillis() + "我是B开始====="); list.add("a1"); Thread.sleep(1000); System.out.println(list); list.add("a2"); System.out.println(System.currentTimeMillis() + "我是B结束====="); } /** * synchronized同步的是持有该方法的对象,这里是Second.class * 所以,不管如何调用,方法a、b总是同步的, * 并且,Second.class被同步使用的时候,是无法通过Second调用其它同步方法的, * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { SecondT1 tt = new SecondT1(); SecondT2 tt2 = new SecondT2(); new Thread(tt).start(); new Thread(tt2).start(); } } class SecondT1 implements Runnable { public void run() { try { Second.a(); } catch (InterruptedException e) { e.printStackTrace(); } } } class SecondT2 implements Runnable { public void run() { try { Second.b(); } catch (InterruptedException e) { e.printStackTrace(); } } }?第三种情况:
/* * Third.java * @author lyjilu 2012-2-26 * @version 1.0 * Copyright (c) 2011-2012, lyjilu. All rights reserved. */ package sync; import java.util.ArrayList; import java.util.List; /** * @author lyjilu 2012-2-26 * @version 1.0 Copyright (c) 2011-2012, lyjilu. All rights reserved. */ public class Third implements Sync { /** * 把list换成 static的,会怎样 */ static List<String> list = new ArrayList<String>(); public void a() throws InterruptedException { System.out.println("进入方法a"); synchronized (list) { list.add("a1"); Thread.sleep(1000); System.out.println(list); list.add("a2"); } System.out.println("离开方法a"); } public void b() throws InterruptedException { System.out.println("进入方法a"); synchronized (list) { list.add("a1"); Thread.sleep(1000); System.out.println(list); list.add("a2"); } System.out.println("离开方法a"); } /** * 如果list非静态,那么list是和实例对象绑定的,也就是说每new一个Third对象, * 那么list就是这个new的对象的属性,所以不同的new对象 * ,是可以同时访问同一方法,并且访问同一块的,只要不在同步块里操作公共对象,那么也不存在同步问题 * 如果list是静态的,那么list是和Third.class绑定的,所以,即使是多个新实例的对象,也不能同时对list进行操作,因为list是相对Third.class,是绝对同步的 * @param args */ public static void main(String[] args) { // 情况一:同一对象,调用有同步块的方法 Third.t1(); // 情况二:不同对象,调用有同步块的方法 Third.t2(); // 情况三:同一对象,调用有同步块的不同方法 Third.t3(); // 情况四:不同对象,调用有同步块的不同方法 Third.t4(); } public static void t1() { Third t1 = new Third(); ThirdT1 tt1 = new ThirdT1(t1); ThirdT2 tt2 = new ThirdT2(t1); new Thread(tt1).start(); new Thread(tt2).start(); } public static void t2() { Third t1 = new Third(); Third t2 = new Third(); ThirdT1 tt1 = new ThirdT1(t1); ThirdT2 tt2 = new ThirdT2(t2); new Thread(tt1).start(); new Thread(tt2).start(); } public static void t3() { Third t1 = new Third(); ThirdT1 tt1 = new ThirdT1(t1); ThirdT3 tt2 = new ThirdT3(t1); new Thread(tt1).start(); new Thread(tt2).start(); } public static void t4() { Third t1 = new Third(); Third t2 = new Third(); ThirdT1 tt1 = new ThirdT1(t1); ThirdT3 tt2 = new ThirdT3(t2); new Thread(tt1).start(); new Thread(tt2).start(); } } class ThirdT1 implements Runnable { Third t; public ThirdT1(Third test) { t = test; } public void run() { try { t.a(); } catch (InterruptedException e) { e.printStackTrace(); } } } class ThirdT2 implements Runnable { Third t; public ThirdT2(Third test) { t = test; } public void run() { try { t.a(); } catch (InterruptedException e) { e.printStackTrace(); } } } class ThirdT3 implements Runnable { Third t; public ThirdT3(Third test) { t = test; } public void run() { try { t.b(); } catch (InterruptedException e) { e.printStackTrace(); } } }? 如果遇见多线程同步问题, 最主要是判断synchronized修饰的方法属于哪个对象(包括静态)或synchronized修饰的对象(同步块)。 如有什么错误,还劳烦指出!