详解Java线程的同步方法

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

内部锁: synchronized 关键字

Java 中的每个对象都有一个与之关联的内部锁(Intrinsic lock). 这种锁也称为监视器(Monitor), 这种内部锁是一种排他锁,可以保障原子性,可见性与有序性.

内部锁是通过 synchronized 关键字实现的.synchronized 关键字修饰代码块,修饰该方法.

修饰代码块的语法:

synchronized( 对象锁 ) {

同步代码块,可以在同步代码块中访问共享数据

}

修饰实例方法就称为同步实例方法

修饰静态方法称称为同步静态方法

上篇文章说了synchronized同步代码块,今天来说说线程的同步方法

2、同步方法

package com.wkcto.intrinsiclock;

/**

* synchronized 同步实例方法

*

把整个方法体作为同步代码块

*

默认的锁对象是 this 对象

* Author: 老崔

*/

public class Test05 {
public static void main(String[] args) {

//先创建 Test01 对象,通过对象名调用 mm()方法

Test05 obj = new Test05();

//一个线程调用 mm()方法

new Thread(new Runnable() {

@Override

public void run() {

obj.mm();

//使用的锁对象this就是obj对象

}

}).start();

//另一个线程调用 mm22()方法

new Thread(new Runnable() {

@Override

public void run() {

obj.mm22();

//使用的锁对象 this 也是 obj

对象, 可以同步

//

new Test05().mm22();

//使用的锁对象 this

是刚刚 new 创建的一个新对象,不是同一个锁对象不能同步

}
}).start();

}

//定义方法,打印 100 行字符串

public void mm(){

synchronized ( this ) {

//经常使用this当前对象作为锁对

象

for (int i = 1; i <= 100; i++) {

System.out.println(Thread.currentThread().getName() + " --> " + i);

}

}

}

//使用 synchronized 修饰实例方法,同步实例方法, 默认 this 作为

锁对象

public synchronized void mm22(){

for (int i = 1; i <= 100; i++) {

System.out.println(Thread.currentThread().getName() + " --> " + i);
}

}

}
复制代码
package com.wkcto.intrinsiclock;

/**

* synchronized 同步静态方法

*

把整个方法体作为同步代码块

*

默认的锁对象是当前类的运行时类对象, Test06.class, 有人

称它为类锁

* Author: 老崔

*/

public class Test06 {

public static void main(String[] args) {

//先创建 Test01 对象,通过对象名调用 mm()方法

Test06 obj = new Test06();

//一个线程调用 m1()方法

new Thread(new Runnable() {

@Override
public void run() {

obj.m1();

//使用的锁对象是 Test06.class

}

}).start();

//另一个线程调用 sm2()方法

new Thread(new Runnable() {

@Override

public void run() {

Test06.sm2();

//使用的锁对象是 Test06.class

}

}).start();

}

//定义方法,打印 100 行字符串

public void m1(){

//使用当前类的运行时类对象作为锁对象,可以简单的理解

为把 Test06 类的字节码文件作为锁对象

synchronized ( Test06.class ) {

for (int i = 1; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + " --> " + i);

}

}

}

//使用 synchronized 修饰静态方法,同步静态方法, 默认运行时类

Test06.class 作为锁对象

public synchronized static void sm2(){

for (int i = 1; i <= 100; i++) {

System.out.println(Thread.currentThread().getName() + " --> " + i);

}

}

}
复制代码
package com.wkcto.intrinsiclock;

/**

* 同步方法与同步代码块如何选择

* 同步方法锁的粒度粗, 执行效率低, 同步代码块执行效率高
*

* Author: 老崔

*/

public class Test07 {

public static void main(String[] args) {

Test07 obj = new Test07();

new Thread(new Runnable() {

@Override

public void run() {

obj.doLongTimeTask();

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

obj.doLongTimeTask();

}

}).start();

}

//同步方法, 执行效率低

public synchronized void doLongTimeTask(){

try {

System.out.println("Task Begin");

Thread.sleep(3000);

//模拟任务需要准备 3 秒

钟

System.out.println("开始同步");

for(int i = 1; i <= 100; i++){

System.out.println(Thread.currentThread().getName() + "-->" + i);

}

System.out.println("Task end");

} catch (InterruptedException e) {

e.printStackTrace();

}

}
//同步代码块,锁的粒度细, 执行效率高

public void doLongTimeTask2(){

try {

System.out.println("Task Begin");

Thread.sleep(3000);

//模拟任务需要准备 3 秒

钟

synchronized (this){

System.out.println("开始同步");

for(int i = 1; i <= 100; i++){

System.out.println(Thread.currentThread().getName() + "-->" + i);

}

}

System.out.println("Task end");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}
复制代码

猜你喜欢

转载自juejin.im/post/7017720122278150158