## 浅析synchronized类锁和对象锁

**

浅析synchronized类锁和对象锁

**
近日重新复习了下java多线程的基本知识,在此写下了作为笔记。若有失实指出还望大家批评指正。
若有朋友转载,请注明原址,谢谢!

老生常谈

java多线程的好处:
充分利用CPU资源,加快程序处理效率,使程序模块化、异步化
多线程所带来的问题:
1.线程的共享资源容易发生冲突
2.可能会发生死锁。
3.启动太多线程会导致资源不足

本文主要就synchronized关键字的使用做简单介绍

synchronized关键字

synchronized关键字和lock是java最常用的锁机制的实现方式。
对比来讲synchronized代码相对简洁,但是效率较lock来说低一些,且没有lock灵活。其逻辑由虚拟机底层实现,使用起来更方便。
lock会在后续博客中介绍。

synchronized的使用情况主要有如下两种:
1.java对象锁:

	//对象锁
	public synchronized void instence() throws InterruptedException{
		System.out.println("Test instence() is begin...");
		Thread.sleep(10000);
		System.out.println("Test instence() is end...");
	}

2.java类锁:

	//类锁
	public static synchronized void classLock() throws InterruptedException{
		System.out.println("Test classLock() is begin...");
		Thread.sleep(10000);
		System.out.println("Test classLock() is end...");
	}

在用法上来说,类锁只比对象锁多了一个static关键字,但是两者锁住的东西却不相同。
先说对象锁,顾名思义,synchronized虽然写在方法上,但是却锁住的是整个对象。也就是说,当一个类中两个方法(A和B)均使用对象锁,在此对象实例化后A方法获取锁调用过程中,其他线程在B方法上是阻塞的。
具体示例如下:

//test类

class Test{
	//对象锁
	public synchronized void instence() throws InterruptedException{
		System.out.println("Test instence() is begin...");
		Thread.sleep(10000);
		System.out.println("Test instence() is end...");
	}
	
	//对象锁2
	public synchronized void instence2() throws InterruptedException{
		System.out.println("Test instence2() is begin...");
		Thread.sleep(10000);
		System.out.println("Test instence2() is end...");
	}
	
	//类锁
	public static synchronized void classLock() throws InterruptedException{
		System.out.println("Test classLock() is begin...");
		Thread.sleep(10000);
		System.out.println("Test classLock() is end...");
	}
}

//两个线程1和2,其中1调用test的instence()方法,2调用instence2()方法

class TestThread implements Runnable{

	Test test;
	public TestThread(Test test) {
		this.test = test;
	}
	
	@Override
	public void run() {
		try {
			test.instence();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

class TestThread2 implements Runnable{

	Test test;
	public TestThread2(Test test) {
		this.test = test;
	}
	
	@Override
	public void run() {
		try {
			test.instence2();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

//主线程

public class SyncLockKinds {
	public static void main(String[] args) throws InterruptedException {
		Test t = new Test();
		new Thread(new TestThread(t)).start();
		new Thread(new TestThread2(t)).start();
		t.instence();
	}
}

运行结果:

Test instence() is begin...
Test instence() is end...
Test instence2() is begin...
Test instence2() is end...
Test instence() is begin...
Test instence() is end...

从结果可以看出每个方法均在前一个方法执行完成后才开始执行。但是instence()和instence2()为不同的两个方法。所以证明synchronized锁住的是对象本身。

此处需注意,得保证多线程所锁的是同一对象,以下代码为错误示范:

public class SyncLockKinds {
	public static void main(String[] args) throws InterruptedException {
		Test t = new Test();
		Test t2 = new Test();
		new Thread(new TestThread(t)).start();
		new Thread(new TestThread2(t2)).start();
//		t.instence();
	}
}

运行结果如下:

Test instence() is begin...
Test instence2() is begin...
Test instence() is end...
Test instence2() is end...

再说类锁:
虚拟机保证每个类只有一个class对象,所以每个类只有一个类锁。
以上代码的Test类不变,线程修改如下:

class TestThread implements Runnable{

	Test test;
	public TestThread(Test test) {
		this.test = test;
	}
	
	@Override
	public void run() {
		try {
			test.instence();
//			Test.classLock();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

class TestThread2 implements Runnable{

	Test test;
	public TestThread2(Test test) {
		this.test = test;
	}
	
	@Override
	public void run() {
		try {
//			test.instence2();
			Test.classLock();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

//主方法

public class SyncLockKinds {

	public static void main(String[] args) throws InterruptedException {
		Test t = new Test();
		new Thread(new TestThread(t)).start();
		new Thread(new TestThread2(t)).start();
//		t.instence();
	}
}

运行结果:

Test instence() is begin...
Test classLock() is begin...
Test instence() is end...
Test classLock() is end...

由此可见,类锁和对象锁锁的并非同一区域

同步代码块

理解对象锁和类锁后 对同步代码块的理解就会简单很多
先说用法:

public class SyncLockKinds {
	public static void main(String[] args) throws InterruptedException {
		Test t = new Test();
		synchronized (t) {
			t.instence2();
			...
		}
		synchronized (test.getClass()) {
			test.instence2();
			...
		}
	}
}

同步代码块相对来说更加灵活,若执行某同步方法,用完此方法后即释放了锁,但若想再执行另一个此对象带锁的同步方法需要重新获取。(此时虚拟机无法保证还是上一个归还锁的人继续获得锁)
而同步块则是当块内代码执行完成才释放锁,执行过程中无需归还锁。

关于synchronized这里就说这些,今后我会持续更新…希望大家多多批评指正,共同进步。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值