记录代码
有兴趣可以运行试试,然后想想。
最终结论只有一条:
“synchronized”关键字同步的始终是
该synchronized修饰的方法的持有对象(同步方法)
该synchronized修饰的对象(同步块)
目前我所知的synchronized关键字用法,分3种情况:
- 普通方法上使用 eg: public synchronized void method(...){...}
- 静态方法上使用 eg: public synchronized static void method(...){...}
- 代码块上使用 eg:....synchronized (obj) {...}
先看下第一种:
/**
* 关于同步关键字 “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修饰的对象(同步块)。
如有什么错误,还劳烦指出!