8锁现象
在并发编程中,一直在谈论锁,但是锁到底是什么呢?它锁的是什么?
首先看下以下8个问题
1、一部手机,两个线程,标准访问,请问先打印邮件还是短信?
2、邮件方法暂停4秒钟,请问先打印邮件还是短信?
3、新增一个普通方法hello()没有同步,请问先打印邮件还是hello?
4、两部手机、请问先打印邮件还是短信?
5、两个静态同步方法,同一部手机,请问先打印邮件还是短信?
6、两个静态同步方法,2部手机,请问先打印邮件还是短信?
7、一个普通同步方法,一个静态同步方法,同一部手机,请问先打印邮件还是短信?
8、一个普通同步方法,一个静态同步方法,2部手机,请问先打印邮件还是短信?
看下程序运行的效果:
1、标准访问,请问先打印邮件还是短信?
public class Test1 {
public static void main(String[] args) {
Phone phone=new Phone();
new Thread(()->{
phone.sendEmail();
},"A").start();
//干扰条件
try{
TimeUnit.SECONDS.sleep(1);
}catch (InterruptedException e){
e.printStackTrace();
}
new Thread(()->{
phone.sendSMS();
},"B").start();
}
}
/**
* 手机,发短信,发邮件
*/
class Phone{
public synchronized void sendEmail(){
System.out.println("sendEmail");
}
public synchronized void sendSMS(){
System.out.println("sendSMS");
}
}
结果:
2、邮件方法暂停4秒钟,请问先打印邮件还是短信?
public class Test2 {
public static void main(String[] args) {
Phone2 phone=new Phone2();
new Thread(()->{
phone.sendEmail();
},"A").start();
//干扰
try{
TimeUnit.SECONDS.sleep(1);
}catch (InterruptedException e){
e.printStackTrace();
}
new Thread(()->{
phone.sendSMS();
},"B").start();
}
}
/**
* 手机,发短信,发邮件
*/
class Phone2{
public synchronized void sendEmail(){
try{
TimeUnit.SECONDS.sleep(4);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("sendEmail");
}
public synchronized void sendSMS(){
System.out.println("sendSMS");
}
}
结果:
3、新增一个普通方法hello()没有同步,请问先打印邮件还是hello?
public class Test3 {
public static void main(String[] args) {
Phone3 phone = new Phone3();
new Thread(() -> { // 一开始就执行了
phone.sendEmail();
}, "A").start();
// 干扰
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> { // 一秒后执行
phone.hello();
}, "B").start();
}
}
/**
*手机,发短信,发邮件
*/
class Phone3 {
public synchronized void sendEmail() {
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendEmail");
}
public synchronized void sendMS() {
System.out.println("sendMS");
}
public void hello() {
System.out.println("hello");
}
}
结果:
4、两部手机、请问先打印邮件还是短信?
public class Test4 {
public static void main(String[] args) {
Phone4 phone1 = new Phone4();
Phone4 phone2 = new Phone4();
new Thread(() -> { // 一开始就执行了
phone1.sendEmail();
}, "A").start();
// 干扰
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> { // 一秒后执行
phone2.sendMS();
}, "B").start();
}
}
// 手机,发短信,发邮件
class Phone4 {
public synchronized void sendEmail() {
// 善意的延迟
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendEmail");
}
public synchronized void sendMS() {
System.out.println("sendMS");
}
}
结果:
5、两个静态同步方法,同一部手机,请问先打印邮件还是短信?
public class Test5 {
public static void main(String[] args) {
Phone5 phone = new Phone5();
new Thread(() -> { // 一开始就执行了
phone.sendEmail();
}, "A").start();
// 干扰
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> { // 一秒后执行
phone.sendMS();
}, "B").start();
}
}
// 手机,发短信,发邮件
class Phone5 {
public static synchronized void sendEmail() {
// 善意的延迟
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendEmail");
}
public static synchronized void sendMS() {
System.out.println("sendMS");
}
}
结果:
6、两个静态同步方法,2部手机,请问先打印邮件还是短信?
public class Test6 {
public static void main(String[] args) {
Phone5 phone = new Phone5();
Phone5 phone2 = new Phone5();
new Thread(() -> { // 一开始就执行了
phone.sendEmail();
}, "A").start();
// 干扰
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> { // 一秒后执行
phone2.sendMS();
}, "B").start();
}
}
// 手机,发短信,发邮件
class Phone6 {
public static synchronized void sendEmail() {
// 善意的延迟
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendEmail");
}
public static synchronized void sendMS() {
System.out.println("sendMS");
}
}
结果:
7、一个普通同步方法,一个静态同步方法,同一部手机,请问先打印邮件还是短信?
public class Test7 {
public static void main(String[] args) {
Phone7 phone = new Phone7();
new Thread(() -> { // 一开始就执行了
phone.sendEmail();
}, "A").start();
// 干扰
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> { // 一秒后执行
phone.sendMS();
}, "B").start();
}
}
class Phone7{
// CLASS
public static synchronized void sendEmail() {
// 善意的延迟
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendEmail");
}
// 对象
// 普通同步方法
public synchronized void sendMS() {
System.out.println("sendMS");
}
}
结果:
8.一个普通同步方法,一个静态同步方法,2部手机,请问先打印邮件还是短信?
public class Test8 {
public static void main(String[] args) {
Phone8 phone = new Phone8();
Phone8 phone2 = new Phone8();
new Thread(() -> { // 一开始就执行了
phone.sendEmail();
}, "A").start();
// 干扰
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> { // 一秒后执行
phone2.sendMS();
}, "B").start();
}
}
class Phone8{
// CLASS
public static synchronized void sendEmail() {
// 善意的延迟
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendEmail");
}
// 对象
// 普通同步方法
public synchronized void sendMS() {
System.out.println("sendMS");
}
}
结果:
总结:
- 锁是一种竞争机制,一个方法加锁,一个方法没有加锁,那么普通方法就会先运行,因为它不要去竞争!
- 被synchornized修饰的同步方法,锁的对象是方法的调用者。谁先调用,谁先执行!
- 被synchronized修饰和static修饰的方法,锁的对象是类的class对象,唯一的!