Java中synchronized使用的一点见解

原创 2016年08月29日 18:33:52

第一篇文章,我先简单介绍下我的情况。普通一本院校的软件工程专业本科学生。现阶段大四,在北京中软国际进行实训。

培训的方向是java 企业级开发。在中软已经培训了一个月多。培训是从零开始学起。所以又从最基本的语法开始学习。第二次学习总是感受颇深。有些地方也有了新的感悟。很多以前不接触的语法或知识也逐渐掌握。

第一次接触java中的synchronize关键字应该是在操作系统课程的实验课上。要求做哲学家进餐问题。使用锁机制,某一线程代码段的原子性。当时使用了一个单独的类,在类中定义了一个静态Object变量当作锁。而所有线程中synchronize代码块均对该object变量加锁,以实现其 查看标识变量并更改标识变量 的原子操作。此处不再详述。

最近重学线程一块。无论是老师讲课,还是网上,总是要求区分synchronize锁方法,锁this,锁对象甚至锁class的区别。而在我的理解,锁方法等同与锁this。

锁方法:

public synchronized void method()
{
  //do some thing
}

public void method() {
		synchronized (this) {
			// do some thing
		}
	}


具有相同的使用效果。即当两个线程同时访问同一个对象的同步代码(锁this)块或同步方法(锁方法),只有一个线程可以得到执行。另一个线程受到阻塞。当两线程访问同一个类的不同对象时,不会产生阻塞。

再说一下锁对象,即锁某个object。

public class MyThread implements Runnable {
	public static void main(String[] args) {
		MyThread m1 = new MyThread();
		MyThread m2 = new MyThread();
		Thread t1 = new Thread(m1);
		Thread t2 = new Thread(m2);
		t1.start(); t2.start();
	}

	public void run() {
		synchronized (Locker.num) {
			for (int i = 0; i < 5; i++)
				System.out.println(Thread.currentThread().getName());
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
public class Locker {
	public static Integer num = 0;
}


相信学习过java的人也一定能理解。这个代码产生的结果将是其中一个线程将同步块执行完后。另一个线程才可能进入同步块执行。即另一个线程被阻塞。

运行结果如下

Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-1
Thread-1
Thread-1
Thread-1
Thread-1


然后这时候,老师或者网上就总会对你说,他们都对同一个对象上了锁。把这个对象锁住了。所以别的线程不能再对其进行加锁,修改等操作。

但我理解的是,对象是一个锁。而被加锁的是{}中的代码。若是同一个对象,那就是同一把锁。既然这把锁已经被别的线程用了且锁住了。所以这个线程就无法获得这个锁,进而进入了等待状态,直到占用了锁的线程将锁释放。

在使用这个对象锁的时候。并不影响其他线程对这个对象进行读或修改的操作。这也就是所谓的加锁的是{}代码块,而非()中的对象。

public class Runnable1 implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			//R1对Locker.num对象进行修改但不上锁
			System.out.println("R1:" + ++Locker.num);
			try {
				Thread.sleep(20);
			} catch (Exception e) {
			}
		}
	}
}
public class Runnable2 implements Runnable {
	@Override
	public void run() {
		// R2对Locker.num对象进行上锁
		synchronized (Locker.num) {
			for (int i = 0; i < 10; i++) {
				System.out.println("R2:" + --Locker.num);
				try {
					Thread.sleep(20);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
public class test {
	public static void main(String[] args) {
		Family family = new Family();
		family.money = 100.0;
		Runnable1 r1 = new Runnable1();
		Runnable2 r2 = new Runnable2();
		Thread t1 = new Thread(r1);
		Thread t2 = new Thread(r2);
		t1.start();
		t2.start();
	}
}
R2:-1
R1:1
R2:0
R1:2
R1:1
R2:-1
R2:0
R1:1
R2:0
R1:2
R2:-1
R1:1
R1:2
R2:0
R1:1
R2:-1
R1:0
R2:-1
R1:0
R2:-2

结果如上图。即R2对Lock.num的加锁并没有影响到R1对Lock.num的读写。

所以无论是锁this,锁object,锁Object.class(其本质也是一个静态对象) 要想知道其是否会造成阻塞,只可单线程进入代码块,而非交叉运行,只需分辨不同线程中同步代码块()中的对象是否为同一个即可。若为同一个。则可以实现阻塞,否则互不影响。

一句话总结,不同线程中,具有相同对象锁的代码块中语句不可交叉执行,会发生阻塞。





版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

Java中JSON解析器的一点见解

本文地址:http://blog.csdn.net/chaijunkun/article/details/7208828,转载请注明出处。本博客会不定期对以前的文章内容进行补充和说明,强烈建议直接看博...

Java学习方法的一点个人见解

FROM : http://www.java2000.net/viewthread.jsp?tid=1691博客-完整版(增加了部分内容):http://blog.csdn.net/java2000_...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

Java学习方法的一点个人见解-完整版!

最近经常有人在论坛,或群里询问,也想报一些java培训班,但是想问一下怎么样学习java最快! 其实,编程的学习正好体现了一句老话:欲速则不达。 今天想给大家谈一下我的对java学习个人的一些见解...

Java中JSON解析器的一点见解

本文地址:http://blog.csdn.net/chaijunkun/article/details/7208828,转载请注明出处。本博客会不定期对以前的文章内容进行补充和说明,强烈建议直接看博...

linux AWK命令的一点使用见解

1、awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息 2、awk处理过程: 依次对每一行进行处理,然后输出 3、awk命令形式:...

关于对Android使用AIDL进行IPC通讯的一点见解

大家应该都使用过AIDL来对Service进行远程调用,大家可能都有过一些疑问,现在我来说说我对于AIDL的理解。 其实对于AIDL进行IPC通讯中,在我们自己写的实现了ServiceConnecti...

js中静态方法(属性)、实例方法(属性)、内部方法(属性)和原型的一点见解

属性 1,私有类型 :私有,即只能自己使用,在下面的例子,就是说只能在这个函数里使用这个属性 ( function(){ var a = "私有属性"; alert(a); //私有...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)