线程八锁
- 一个对象里面如果有多个synchronized方法,某一时刻内,只要一个线程去调用其中的一个synchronized方法了,其它的线程都只能等待,换句话说,某一时刻内,只能有唯一一个线程去访问这些synchronized方法
- 锁的是当前对象this,被锁定后,其它的线程都不能进入到当前对象的其它的synchronized方法
- 加个普通方法后发现和同步锁无关。
- 换成两个对象后,不是同一把锁了,情况立刻变化。
- 都换成静态同步方法后,情况有变化。
- 所有的非静态同步方法用的都是同一把锁——实例对象本身,也就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法使用的是不同的锁,所以无须等待该实例对象已获取锁的非静态同步方法释放锁就可以获取他们自己的锁。
- 所有的静态同步方法用的也是同一把锁——类对象本身,这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。但是一旦一个静态方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同步方法之间,只要它们同一个类的实例对象!
- 线程八锁的关键:
- ①非静态方法的锁默认为 this ,静态方法的锁为 对对应的Class实例
- ②某一时刻内,只有一个线程持有锁,无论有几个方法。
题目
/*
* 题目:判断打印的是 "one" or "two"?
* 1. 两个普通同步方法,两个线程,标准打印,打印? //one two
* 2. 新增Thread.sleep() 给getOne() 打印? // one two
* 3. 新增普通方法getThree() , 打印 ? // three one two
* 4. 两个普通的同步方法,两个Number 对象 ,打印? // two one
* 5. 修改getOne()为静态同步方法 打印?// two one
* 6. 修改两个方法均为静态同步方法,一个Number对象//one two
* 7. 一个静态同步方法,一个非静态同步方法,两个Number对象。打印? // two one
* 8. 两个静态同步方法,两个Number对象,打印? // one two
*
* 线程八锁的关键:
* ①非静态方法的锁默认为 this ,静态方法的锁为 对对应的Class实例
* ②某一时刻内,只有一个线程持有锁,无论有几个方法。
*/
public class TestThread8Monitor {
public static void main(String[] args) {
Number number = new Number();
new Thread(new Runnable() {
@Override
public void run() {
number.getOne();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
number.getTwo();
}
}).start();
}
}
class Number{
public synchronized void getOne() {
System.out.println("one");
}
public synchronized void getTwo() {
System.out.println("two");
}
}
- 在getOne方法里面打印前加入下列代码
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
打印结果还是one two
- 加入新的方法
public void getThree() {
System.out.println("three");
}
//新增一个线程
new Thread(new Runnable() {
@Override
public void run() {
number.getThree();
}
}).start();
输入结果为 three one two
- 新增一个number对象,并将main方法代码修改如下形式
public static void main(String[] args) {
Number number = new Number();
Number number2 = new Number();
new Thread(new Runnable() {
@Override
public void run() {
number.getOne();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// number.getTwo();
number2.getTwo();
}
}).start();
// new Thread(new Runnable() {
//
// @Override
// public void run() {
// number.getThree();
// }
// }).start();
}
输入结果为 two one
- 将getOne变为static 方法,且使用一个对象number1调用两个getOne和getTwo
public static synchronized void getOne() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("one");
}
输出结果为 two one
-
修改两个方法getOne()和getTwo(),然后一个对象,两个线程同时调用,结果为
-
修改getOne()为静态同步方法 getTwo()为非静态同步方法,然后两个对象调用,main方法代码如下
public static void main(String[] args) {
Number number = new Number();
Number number2 = new Number();
new Thread(new Runnable() {
@Override
public void run() {
number.getOne();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// number.getTwo();
number2.getTwo();
}
}).start();
}
结果 two one 如下 :
- 两个静态同步方法,两个Number对象,main方法代码如7.
结果为 one two
最终修改完的代码
public class TestThread8Monitor {
public static void main(String[] args) {
Number number = new Number();
Number number2 = new Number();
new Thread(new Runnable() {
@Override
public void run() {
number.getOne();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// number.getTwo();
number2.getTwo();
}
}).start();
// new Thread(new Runnable() {
//
// @Override
// public void run() {
// number.getThree();
// }
// }).start();
}
}
class Number{
public static synchronized void getOne() {//Number.class
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("one");
}
public static synchronized void getTwo() {
System.out.println("two");
}
public void getThree() {//this
System.out.println("three");
}
}