Synchronized 使用方式
修饰到方法上
以下的m1\m2方法上加锁相当于,把锁加在this对象上,所以只有m1下城执行完成m2线程才可以继续执行
public class T1 {
private static synchronized void m1() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
System.out.println("m1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static synchronized void m2() {
System.out.println("m2");
}
public static void main(String[] args) {
new Thread(T1::m1, "m1").start();
new Thread(T1::m2, "m2").start();
}
}
修饰到对象上
下面的示例是启动两个线程进行对count字段--
,一个加锁一个不加锁,最后的结果没有得到预期的效果【按照顺序进行递减】,是因为两个线程在并行执行都可以访问到count字段,所以没得到预期的效果。
public class T2 {
private static int count = 10;
private static final Object o = new Object();
private static void m1() {
synchronized (o) {
m3();
}
}
private static void m2() {
m3();
}
private static void m3() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
count--;
System.out.println(Thread.currentThread().getName() + " count: " + count);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Thread(T2::m1, "m1").start();
new Thread(T2::m2, "m2").start();
}
}
如果要达到预期的效果两个线程同时对操作方法加锁
public class T2 {
private static int count = 10;
private static final Object o = new Object();
private static void m1() {
synchronized (o) {
m3();
}
}
private static void m2() {
synchronized (o) {
m3();
}
}
private static void m3() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
count--;
System.out.println(Thread.currentThread().getName() + " count: " + count);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Thread(T2::m1, "m1").start();
new Thread(T2::m2, "m2").start();
}
}
其实synchronized还可以修饰T.class
,本质上synchronized修饰的就是一个实例
从以上的例子来看,synchronized 修饰的是一个实例,锁在java对象中的体现是在,对象头里jvm
中采用两个字节来存储对象头,具体是怎么实现的需要阅读代码和查看java对象的字节码在jvm的存储方式.