synchronized同步方法2

3 篇文章 0 订阅
2 篇文章 0 订阅
  
  接上一篇synchronized同步方法
关键字synchronized取得的锁都是对象锁,而不是把一段代码或方法当作锁。对于多个线程同时执行一个对象的一个同步方法,哪个线程先执行带synchronized关键字的方法,哪个线程就持有了该方法所属对象的锁Lock,那么其他线程只能呈等待状态。

2. 如何通过synchronized关键字解决脏读
代码:

package testSynchronized;

public class PublicVar {
    public String username ="A";
    public String password = "AA";
    synchronized public void setValue(String username,String password){
        try{
            this.username = username;
            Thread.sleep(5000);
            this.password = password;
            System.out.println("setValue method thread name = "+Thread.currentThread().getName()+" username = "+username
                    +", password = "+password);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }
    
    
      public void getValue(){
        System.out.println("getValue method thread name ="+Thread.currentThread().getName()+
                " username = "+username +", password = "+password);
      }


}



package testSynchronized;

public class ThreadA extends Thread {
	private PublicVar publicVar;
	public ThreadA(PublicVar publicVar){
		this.publicVar = publicVar;
	}
	@Override
	public void run() {
		publicVar.setValue("B", "BB");
	}
	
}

package testSynchronized;

public class Test {
	public static void main(String[] args) {
	PublicVar publicVar = new PublicVar();
	ThreadA threadA = new ThreadA(publicVar);
	threadA.start();
	try {
		Thread.sleep(1000);
	} catch (InterruptedException e) {
		
		e.printStackTrace();
	}
	publicVar.getValue();
	}
}

运行结果:
getValue method thread name =main username = B, password = AA//出现脏读
setValue method thread name = Thread-0 username = B, password = BB

若将getValue() 前加上synchronized关键字,就不会出现这种情况了。


 sunchronized public void getValue(){
        System.out.println("getValue method thread name ="+Thread.currentThread().getName()+
                " username = "+username +", password = "+password);
      }



运行结果:

setValue method thread name = Thread-0 username = B, password = BB
getValue method thread name =main username = B, password = BB



当A线程调用anyObject对象的同步方法(加入synchronized关键字)X时,A线程就获得了X方法锁,更准确的将是:获得了X方法所属对象的锁,所以其他线程必须等到A线程执行完毕才可以调用X方法,但是B线程可以随意调用其他的非synchronized同步方法。
当A线程调用了anyObject对象的同步方法时X时,A线程就获得了X方法所属对象的锁,所以其他线程必须等到A线程执行完毕才可以调用X方法,二如果B线程调用了其他的同步方法(不是X方法),也必须等到A线程将X方法执行完,也就是A线程释放了对象锁后才可以调用。
3.synchronized 锁重入
   关键字synchronized拥有锁重入的功能,也就是在使用synchronized时,当一个线程得到了一个对象锁后,再次请求此对象锁时是可以再次得到的该锁的。这也证明在一个synchronized方法/块的内部调用本类的其他synchronized方法/块时,是永远可以得到锁的。
代码:

package testSynchronized;

public class Service {
	synchronized public void service1(){
		System.out.println("service1");
		service2();
	}

	synchronized public void service2() {
		System.out.println("service2");
		service3();
		
	}

	synchronized public void service3() {
		System.out.println("service3");
	}
}

package testSynchronized;

public class Main {
	public static void main(String[] args) {
		Thread thread1 = new Thread(){
			@Override
			public void run() {
				super.run();
				Service service = new Service();
				service.service1();
			}
			
		};
		thread1.start();
	}
	
}

运行结果:


service1
service2
service3

    “可重入锁”的概念是:自己可以再次获取自己的内部锁。 例如:由1个线程获得了某个对象的锁,此时这个对象锁还没有被释放,当该线程再次想要获取这个对象锁时是可以获取的,如果不可获取锁重入的话,就会造成死锁。

可重入锁也支持在父子类继承的环境中。

package testSynchronized;


public class Parent {
	public int i = 10;
	synchronized public void operateParentMethod(){
		try {
			i--;
			System.out.println("Parent print i = "+i);
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}
}

package testSynchronized;

public class Son extends Parent {
	synchronized public void operateSonMethod(){
		try {
			while(i >0){
				i--;
				System.out.println("Son print i = "+i);
				Thread.sleep(1000);
				this.operateParentMethod();//子类在自己的同步方法中调用父类的同步方法
			}	
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

package testSynchronized;

public class MyThread extends Thread {

	@Override
	public void run() {
		super.run();
		Son son = new Son();
		son.operateSonMethod();
	}
	
}

package testSynchronized;

public class Run {
	public static void main(String[] args) {
		Thread thread = new MyThread();
		thread.start();
	}
}
运行结果:
Son print i = 9
Parent print i = 8
Son print i = 7
Parent print i = 6
Son print i = 5
Parent print i = 4
Son print i = 3
Parent print i = 2
Son print i = 1
Parent print i = 0

运行结果说明:当存在父子类继承关系时,子类完全可以通过“可重入锁”调用父类的同步方法。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值