跟着实例学习java多线程3-synchronized的多种写法有何区别?_沉默的多类写法-程序员宅基地

技术标签: 并发编程  

同步代码块是一种有效实现操作原子性的方法,上一章我们讲了一些同步的原子操作的基础。

现在我们回忆一下上一章的两个问题。

1:不同的synchronized的写法有什么区别,又该怎么写创建线程的代码呢?

以class实例对象作为锁的写法

写法1

package com.home.thread;

/**
 * @author gaoxu
 * 
 */
public class SafeThread {
	@safe
	public  void testPrint(){
		 synchronized(SafeThread.class){
			System.out.println("Enter testPrint method !");
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
		
				e.printStackTrace();
			}	
			System.out.println("Exit testPrint method !");
		}
	}
	
}


写法2

package com.home.thread;

/**
 * @author gaoxu
 * 
 */
public class SafeThread {
		
	public static   synchronized  void testPrint(){
			System.out.println("Enter testPrint method !");
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
		
				e.printStackTrace();
			}	
			System.out.println("Exit testPrint method !");
	}
	
}

以上两种写法是以class实例对象为锁的写法,这两种写法的调用线程该怎么写呢?让我们来看下面的例子

写法1,创建当前对象实例,并使用对象实例初始化线程。

package com.home.thread;

/**
 * @author gaoxu
 * 
 */
public class ThreadStart {
	
	public static void main(String[] para){
		SafeThread safe = new SafeThread();
		for(int i=0;i<3;i++){
			ThreadRead1 t1 = new ThreadRead1(safe);
			t1.start();
		}
	}
}

package com.home.thread;

/**
 * @author gaoxu
 *
 */
public class ThreadRead1 extends Thread{
	SafeThread safe = null;
	public ThreadRead1(){
	}
	public ThreadRead1(SafeThread o){
		safe = o;
	}

	public void run()
	{
		safe.testPrint();
	}

}


写法2,可以在线程中创建类实例。

package com.home.thread;

/**
 * @author gaoxu
 * 
 */
public class ThreadStart {
	
	public static void main(String[] para){
		for(int i=0;i<3;i++){
			ThreadRead1 t1 = new ThreadRead1();
			t1.start();
		}
	}
}</span>


<span style="font-size:14px;">package com.home.thread;

/**
 * @author gaoxu
 *
 */
public class ThreadRead1 extends Thread{
	SafeThread safe = null;
	public ThreadRead1(){
	}
	
	public void run()
	{
		safe = new SafeThread();
		safe.testPrint();
	}

}


这两总写法可以起到相同的作用,都可以实现原子的操作,实现同步互斥的调用。


创建内部同步代码块,以当前实例对象作为锁的对象。

写法1

package com.home.thread;

/**
 * @author gaoxu
 * 
 */
public class SafeThread {
		public   synchronized  void testPrint(){
			System.out.println("Enter testPrint method !");
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
		
				e.printStackTrace();
			}	
			System.out.println("Exit testPrint method !");
	}
	
}


package com.home.thread;

/**
 * @author gaoxu
 * 
 */
public class SafeThread {
		public  void testPrint(){
		synchronized(this){
			System.out.println("Enter testPrint method !");
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
		
				e.printStackTrace();
			}	
			System.out.println("Exit testPrint method !");
		}

	
}
	
}<span style="font-size:14px;">
</span>
package com.home.thread;

/**
 * @author gaoxu
 * 
 */
public class SafeThread {
		Object a = new Object();

		
	public   void testPrint(){
		synchronized(a){
			System.out.println("Enter testPrint method !");
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
		
				e.printStackTrace();
			}	
			System.out.println("Exit testPrint method !");
		}

	
}
	
}

这三种写法都是以类的当前实例对象作为锁对象,所以线程调用写法如下;

package com.home.thread;

/**
 * @author gaoxu
 * 
 */
public class ThreadStart {
	
	public static void main(String[] para){
		SafeThread safe = new SafeThread();//当前实例对象
		for(int i=0;i<3;i++){
			ThreadRead1 t1 = new ThreadRead1(safe);
			t1.start();
		}
	}
}
package com.home.thread;

/**
 * @author gaoxu
 *
 */
public class ThreadRead1 extends Thread{
	SafeThread safe = null;
	public ThreadRead1(){
	}
	public ThreadRead1(SafeThread o){
		safe = o;
	}

	public void run()
	{
		safe.testPrint();
	}

}

下面让我们来看一下以class对象和当前对象的区别:

    类.class和static synchronized是对该类所有实例对象枷锁。

    synchronized(this),synchronized,synchronized(object)都是对类的当前实例对象加锁。

具体说明:

      synchronized是对类的当前实例进行加锁,防止其他线程同时访问该类的当前实例的所有synchronized块。static synchronized是控制类的所有实例的访问了,static synchronized是限制线程同时访问jvm中该类的所有实例对应的代码快。在类中某方法或某代码块中有 synchronized,那么在生成一个该类实例后,该类也就有一个监视块,放置线程并发访问该实例synchronized保护块,这个保护块只对当前实例有效,而static synchronized则是所有该类的实例公用一个监视块,放置线程并发访问该类所有实例的保护块,synchronized相当于 this.synchronized,而
static synchronized相当于Something.synchronized。

2:死锁、活跃性问题都是怎么产生的。

后续章节我们重点讨论。

今天的问题是:

1:线程安全除了原子操作还有什么需要注意的。

2:如何确定自己需要实现一个线程安全类。


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/andy_gx/article/details/42932913

智能推荐

Dijkstra最短路径算法(针对加权有向图)_liujianfeng1984-程序员宅基地

文章浏览阅读5.2k次。indexMinPQ.h#ifndef _INDEX_MIN_PQ_H_#define _INDEX_MIN_PQ_H_#define INDEX_MIN_PQ_TEST 0typedef struct{ int index; double cmpNum;} INDEX_MIN_PQ_DATA;typedef struct{ int _liujianfeng1984

25.WEB安全基础知识一 网站基础知识_web安全中网站基础是指什么-程序员宅基地

文章浏览阅读1.5k次。1、网站基础知识01 网站访问过程域名->ip->服务器-服务器上的网站网站->浏览器02 网站的基础组成部分html(超文本标记语言):定义页面的内容div+css(层叠样式表):定义页面的布局javascript(js脚本语言):处理页面的动作03 网站类型静态网站:没有程序语言而且没有数据库、不可进行交互、后缀多为html/htm/shtml。动态网站:程序语言、逻辑语言、有数据库、可交互、而且后缀多为php/asp/aspx/jsp/伪静态html等。 _web安全中网站基础是指什么

卧槽!你竟然连SpringBoot中的线程池都不会用。。。-程序员宅基地

文章浏览阅读468次。点击上方蓝色“java大数据修炼之道”,选择“设为星标”每晚九点: 技术干货 ???? 必定奉上哈喽,各位新来的小伙伴们,大家好!由于公众号做了改版,为了保证公众号的资源能准时推送到你..._springboot线程池 线程名前缀不起作用

cesium自定义的弹窗 Popup弹窗(可随球放大缩小,移动)_cesium popup-程序员宅基地

文章浏览阅读1.2w次,点赞30次,收藏140次。# 效果图中效果源代码在下面的封装栏中# 基本思路添加一个鼠标左键点击事件,当鼠标点击时,利用vue2.0中 Vue.extend() 动态添加一个dom元素,将DOM元素渲染到cesium容器中,并利用cesium中提供的 viewer.scene.postRender 实时更新坐标位置。思路很简单,接下来我们进行实现。# 实现方法 1. 首先我们需要生成一个球体做我们标记的容器。viewer = new Cesium.Viewer('cesiumContainer',{ _cesium popup

相机相关参数及视野计算_相机视野大小怎么计算-程序员宅基地

文章浏览阅读2.1w次,点赞12次,收藏62次。CCD尺寸就是靶面尺寸,一般是以英尺为单位,是靶面的斜边长。像素尺寸一般以毫米或微米为单位,是靶面的长和宽。以以下参数为例:监测标志物像素按以下公式计算:Di=fDr/Zdx,其中Di为标志物所占像素直径,f为焦距,Dr为标志物直径,Z为实际距离,dx为每一个像素在x方向的物理尺寸。依据上图,算例一:假设焦距200mm,标志物直径1000mm,实际距离500000mm。dx已知为0.0025mm/pixel,则Di=2001000/5000000.0025=160个像素,即标志所占160个像素。算._相机视野大小怎么计算

多元线性回归,岭回归,lasso回归(具体代码(包括调用库代码和手写代码实现)+一点点心得)_多元线性回归代码-程序员宅基地

文章浏览阅读3.8k次,点赞11次,收藏53次。最近数据挖掘导论老师布置了一项作业,主要就是线性回归的实现,笔者之前听过吴恩达的线性回归的网课,但一直没有进行代码的实现,这次正好相对系统的整理一下,方便各位同学的学习,也希望能够对其进行优化,优化的点最后再说。笔者写这篇博客也为了给实验报告打底稿,各位小伙伴2021年9月30号提交报告的时候别跟我实验报告一样啊,打回的话苦的是自己人,到时候我直接一波举报,哈哈哈。不过,发表这篇文章笔者是真的希望给没有实现的同学提供一点小小的帮助或者提供一点小小的想法。一.实验指导书:数据挖掘实验指导书数据预处_多元线性回归代码

随便推点

ARC 107 解题报告 A.数学(多项式相乘的性质)B(枚举、计算贡献)C(思维、并查集)D(DP(非整数转化)E(打表找结论)F(网络流不会))_arc107-程序员宅基地

文章浏览阅读128次。A - Simple Math题目:求∑a=1A∑b=1B∑c=1C\sum_{a=1}^{A}\sum_{b=1}^{B}\sum_{c=1}^{C}a=1∑A​b=1∑B​c=1∑C​的值ll a,b,c;ll inv2;ll solve(){ ll res=((a+1)*a%mod*inv2%mod)%mod; res=((res*(b+1)%mod)*b%mod*inv2%mod)%mod; res=((res*(c+1)%mod)*c%mod*inv2%mod)%mod; re_arc107

中山纪中游记Day12+8.12模拟赛题解-程序员宅基地

文章浏览阅读126次。Part.I 游记今天的题真的难。。。第一题似乎可以用线段树乱搞,然后我就敲了个线段树上去。和暴力拍了将近40分钟后我确定它已经是正确的然后我就交了。结果考完后发现我开数组时开小了。。。于是100→30…QAQ。。。第二题直接打的暴力。。。结果打T了。。。半分也没有。。。第三题勉强拿到了人口普查的分QAQ。。。woc 如果我第一题拿满的话我就rank 2了。。。Part.II 题解...

RTC定时开机闹钟-程序员宅基地

文章浏览阅读856次。  RTC是Real Time Clock的简称,它在硬件电路上单独供电,当系统关机时,CPU和其他外部硬件设备全部掉电,但是RTC仍然继续工作.  HWCR (Hibernate Wakeup Control Register)是一个控制休眠唤醒的寄存器,如果我们要使用休眠状态下RTC唤醒的功能,我们需要打开它的第0位ELAM(RTC Alarm Wakeup enable),当ELAM置1..._rt-186闹钟

linux图形界面装mysql_ubuntu 安装图形界面-程序员宅基地

文章浏览阅读169次。安装基本图形界面:apt-get install xorg gdm ssh你可以用/etc/init.d/gdm start 测试是否成功.一般是肯定成功的,所以你可以不用试了,然后再用’Ctrl + Alt + F1′.切换出去,因为我们还有很多东西要继续安装Gnome桌面:apt-get install gnome-session gnome-menus gnome-panel metacit..._tango-icon-theme

萧子术的第一道编程算法题_算法题:鹏鹏很喜欢吉他,老师让他进行拨琴弦-程序员宅基地

文章浏览阅读94次。标题:用java实现 给定一个整数数组 nums 和一个整数目标值target,请你在该数组中找出 和为目标值的那两个 整数,并返回它们的数组下标。你可以假设每种输入只**会对应一个答案。**但是,数组中同一个元素不能使用两遍。你可以按任意顺序返回答案。大家好!我是 萧子术 这是我第一次写博客。以下内容将记录并督促自己每天写一道算法题。加油~奥利给!``2021年1月16日,地点:家里 天气:阴天这是第一道题目题目内容:给定一个整数数组 nums 和一个整数目标值target,请你在该数组_算法题:鹏鹏很喜欢吉他,老师让他进行拨琴弦

策略模式_为什么策略模式查出来的对象 放进list中会被覆盖-程序员宅基地

文章浏览阅读2.4k次。策略模式定义了算法族,这些算法被分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。 这是《深入浅出设计模式》对策略模式的定义,这个定义说得很准确,但是书中的示例却举得不好,让我对策略模式的理解总是“一会儿感觉理解了,一会儿感觉没有理解”。直到看了《Effective Java》第二版第21条,用函数对象表示策略,才终于只是处于“感觉理解了”的状态了。根据自己的理解,写了_为什么策略模式查出来的对象 放进list中会被覆盖