文章目录
- 前言
- 一、synchronized是什么
- 二、synchronized的三种写法
- 1、同步代码块
- 2、在实例方法上使用synchronized
- 3、在静态方法上使用synchronized
- 总结
前言
总结一下自己在学习Synchronized 以及它的三种写法。
一、synchronized是什么?
synchronized是由JVM实现的一种互斥同步的一种方式,被synchronized修饰过的程序块在编译前后被编译器生成了monitorenter和monitorexit两个字节码指令。
如果这个方法使用了synchronized的时候,代表它加上了锁,运行此方法的时都要检查它有没有被其他线程正在使用(或者该类的其他同步方法),有的话要等它使用完,没有的话则直接锁定调用者,然后直接运行。它包括两种用法:synchronized方法和synchronized块。
二、synchronized的三种写法
1、同步代码块
代码如下(示例):
package com.demo;
public class Demo {
public static void main(String[] args) throws InterruptedException {
MyClass mc=new MyClass();
Thread t1=new MyThread(mc);
Thread t2=new MyThread(mc);
t1.setName("t1");
t2.setName("t2");
t1.start();
Thread.sleep(1000);//这个睡眠的作用 是为了保证t1线程先执行。
t2.start();
}
}
class MyThread extends Thread {
private MyClass mc;
public MyThread (MyClass mc) {
this.mc = mc;
}
public void run(){
if(Thread.currentThread().getName().equals("t1")) {
mc.doSome();
}
if(Thread.currentThread().getName().equals("t2")) {
mc.doOther();
}
}
}
class MyClass{
//synchronized出现再类方法上,表示锁this。
public synchronized void doSome(){
System.out.println("doSome 执行开始");
try {
Thread .sleep(1000*5);//睡眠五秒
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("doSome 执行结束");
}
public void doOther() {
System.out.println("doOther 执行开始");
System.out.println("doOther 执行结束");
}
}
doOther方法执行的时候不需要等待被修饰过的doSome方法结束,因为doOther方法没有被synchronized修饰,所以它不用排队等待。
2、在实例方法上使用synchronized
代码如下(示例):
package com.demo; public class Demo { public static void main(String[] args) throws InterruptedException { MyClass mc=new MyClass(); Thread t1=new MyThread(mc); Thread t2=new MyThread(mc); t1.setName("t1"); t2.setName("t2"); t1.start(); Thread.sleep(1000);//这个睡眠的作用 是为了保证t1线程先执行。 t2.start(); } } class MyThread extends Thread { private MyClass mc; public MyThread (MyClass mc) { this.mc = mc; } public void run(){ if(Thread.currentThread().getName().equals("t1")) { mc.doSome(); } if(Thread.currentThread().getName().equals("t2")) { mc.doOther(); } } } class MyClass{ //synchronized出现再类方法上,表示锁this。 public synchronized void doSome(){ System.out.println("doSome 执行开始"); try { Thread .sleep(1000*5);//睡眠五秒 } catch (Exception e) { e.printStackTrace(); } System.out.println("doSome 执行结束"); } public synchronized void doOther() { System.out.println("doOther 执行开始"); System.out.println("doOther 执行结束"); } }
在两个方法前都加上synchronized修饰,doOther方法执行的时候需要等待doSome方法结束完之后才执行doSome,因为锁被doSome占了,所以要排队等待。 我们再开启一个线程:package com.demo; public class Demo { public static void main(String[] args) throws InterruptedException { //开启两个线程 MyClass mc1=new MyClass(); MyClass mc2=new MyClass(); Thread t1=new MyThread(mc1); Thread t2=new MyThread(mc2); t1.setName("t1"); t2.setName("t2"); t1.start(); Thread.sleep(1000);//这个睡眠的作用 是为了保证t1线程先执行。 t2.start(); } } class MyThread extends Thread { private MyClass mc; public MyThread (MyClass mc) { this.mc = mc; } public void run(){ if(Thread.currentThread().getName().equals("t1")) { mc.doSome(); } if(Thread.currentThread().getName().equals("t2")) { mc.doOther(); } } } class MyClass{ //synchronized出现再类方法上,表示锁this。 public synchronized void doSome(){ System.out.println("doSome 执行开始"); try { Thread .sleep(1000*5);//睡眠5秒 } catch (Exception e) { e.printStackTrace(); } System.out.println("doSome 执行结束"); } public synchronized void doOther() { System.out.println("doOther 执行开始"); System.out.println("doOther 执行结束"); } }
doOther方法执行的时候不需要等待doSome方法结束,因为MyClass对象是两个,两把锁,互不干涉。
3、在静态方法上使用synchronized
package com.demo;
public class Demo {
public static void main(String[] args) throws InterruptedException {
//开启两个线程
MyClass mc1=new MyClass();
MyClass mc2=new MyClass();
Thread t1=new MyThread(mc1);
Thread t2=new MyThread(mc2);
t1.setName("t1");
t2.setName("t2");
t1.start();
Thread.sleep(1000);//这个睡眠的作用 是为了保证t1线程先执行。
t2.start();
}
}
class MyThread extends Thread {
private MyClass mc;
public MyThread (MyClass mc) {
this.mc = mc;
}
public void run(){
if(Thread.currentThread().getName().equals("t1")) {
mc.doSome();
}
if(Thread.currentThread().getName().equals("t2")) {
mc.doOther();
}
}
}
class MyClass{
//synchronized出现再类方法上,表示锁this。
public synchronized static void doSome(){
System.out.println("doSome 执行开始");
try {
Thread .sleep(1000*5);//睡眠5秒
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("doSome 执行结束");
}
public synchronized static void doOther() {
System.out.println("doOther 执行开始");
System.out.println("doOther 执行结束");
}
}
doOther方法执行的时候不需要等待doSome方法结束,因为静态方法是类锁,不管创建了几个对象,类锁只有一把。
总结
对象锁:1个对象1把锁,100个对象有100把锁。
类锁:100个对象,全部都是这一把锁。