一、synchronized修饰实例方法:
synchronized修饰实例方法,实际上是对调用该方法的对象加锁。
场景1:同一实例对象在两个线程中分别调用该对象的两个同步实例方法
public class Car {
public synchronized void runing1(Thread thread){
System.out.println(thread.getName()+ " car1 得到锁");
System.out.println("------ car1 is running ------");
working();
System.out.println(thread.getName()+ " car1 释放锁");
System.out.println();
}
public synchronized void runing2(Thread thread){
System.out.println(thread.getName()+ " car2 得到锁");
System.out.println("------ car2 is running ------");
working();
System.out.println(thread.getName()+ " car2 释放锁");
System.out.println();
}
public static void working(){
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
public class Test01 {
public static void main(String[] args) {
Car car = new Car();
//线程1
Thread t1 = new Thread(){
@Override
public void run() {
car.runing1(Thread.currentThread()); //同步实例方法1
}
};
t1.start();
//线程2
Thread t2 = new Thread(){
@Override
public void run() {
car.runing2(Thread.currentThread()); //同步实例方法2
}
};
t2.start();
}
}
结果:两个线程依次执行,说明产生互斥,因为实例方法加锁针对的是实例对象,当前对象调用一个synchronized方法时,其他同步方法需要等待其执行结束并释放锁之后才能执行。
场景二:两个对象在两个线程中分别调用同一个同步实例方法
public class test02 {
public static void main(String[] args) {
Car car1 = new Car();
Car car2 = new Car();
//线程1 对象1
Thread t1 = new Thread(){
@Override
public void run() {
car1.runing1(Thread.currentThread()); //同步实例方法1
}
};
t1.start();
//线程2 对象2
Thread t2 = new Thread(){
@Override
public void run() {
car2.runing1(Thread.currentThread()); //同步实例方法1
}
};
t2.start();
}
}
结果 :两个线程同时进行,因为是两个对象,实例方法加锁针对的是实例对象,并不是方法,所以可以并发执行,不会互斥。
此外,同一个对象分别在两个线程中分别调用同步实例方法和非同步方法(未用synchronized修饰的方法),不会出现互斥,这里不再展示。synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行,而不会限制其他非synchronized方法。非synchronized方法不需要占有该对象,因此不会互斥。
synchronized修饰类方法:
synchronized修饰静态方法,实际上是对该类进行加锁,而不属于某个对象。
场景一:用类直接在两个线程中调用两个不同的同步静态方法
public class Car {
public static synchronized void staticRuning1(Thread thread){
System.out.println(thread.getName()+ " static car1 得到锁");
System.out.println("------ static car1 is running ------");
working();
System.out.println(thread.getName()+ " static car1 释放锁");
System.out.println();
}
public static synchronized void staticRuning2(Thread thread){
System.out.println(thread.getName()+ " static car2 得到锁");
System.out.println("------ static car2 is running ------");
working();
System.out.println(thread.getName()+ " static car2 释放锁");
System.out.println();
}
public static void working(){
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
public class test02 {
public static void main(String[] args) {
//线程1 类
Thread t1 = new Thread(){
@Override
public void run() {
Car.staticRuning1(Thread.currentThread()); //同步类方法1
}
};
t1.start();
//线程2 类
Thread t2 = new Thread(){
@Override
public void run() {
Car.staticRuning2(Thread.currentThread()); //同步类方法2
}
};
t2.start();
}
}
结果:产生互斥,因为对静态方法加锁,实际上是对类加锁,类只有一个。因此当一个同步静态方法被访问时,该类已处于被锁状态。此时其他同步静态方法不能被访问(未用synchronized修饰的静态方法仍可以访问)
场景二:两个线程分别调用同步类方法和同步实例方法
public class test03 {
public static void main(String[] args) {
Car car = new Car();
//线程1 实例对象
Thread t1 = new Thread(){
@Override
public void run() {
car.runing1(Thread.currentThread()); //同步实例方法1
}
};
t1.start();
//线程2 类
Thread t2 = new Thread(){
@Override
public void run() {
Car.staticRuning2(Thread.currentThread()); //同步类方法2
//面试中一个面试官问如果静态方法通过实例来调用,那锁的是实例还是类呢?
//当然还是类了,这里可以把Car.staticRuning2改成car.staticRuning2,通过实例对象来调用静态方法
//结果还是一样的。
}
};
t2.start();
}
}
结果:不会互斥,锁对象不同,一个是对实例对象加锁,一个对类加锁,这里直接调用Car类Car.staticRuning2(Thread.currentThread())
其实跟调用car对象 car.staticRuning2(Thread.currentThread())
效果一样,因为静态方法不属于某个实例,而属于类本身。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/37791.html