浅谈Java多线程的同步问题 【转】
多线程的同步依靠的是对象锁机制,synchronized关键字的背后就是利用了封锁来实现对共享资源的互斥访问。
下面以一个简单的实例来进行对比分析。实例要完成的工作非常简单,就是创建10个线程,每个线程都打印从0到99这100个数字,我们希望线程之间不会出现交叉乱序打印,而是顺序地打印。
先来看第一段代码,这里我们在run()方法中加入了synchronized关键字,希望能对run方法进行互斥访问,但结果并不如我们希望那样,这是因为这里synchronized锁住的是this对象,即当前运行线程对象本身。代码中创建了10个线程,而每个线程都持有this对象的对象锁,这不能实现线程的同步。
代码Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->package com.vista; class MyThread implements java.lang.Runnable
{
private int threadId; public MyThread(int id)
{
this.threadId = id;
}
@Override
public synchronized void run()
{
for (int i = 0; i < 100; ++i)
{
System.out.println("Thread ID: " + this.threadId + " : " + i);
}
}
}
public class ThreadDemo
{
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException
{
for (int i = 0; i < 10; ++i)
{
new Thread(new MyThread(i)).start();
Thread.sleep(1);
}
}
}
从上述代码段可以得知,要想实现线程的同步,则这些线程必须去竞争一个唯一的共享的对象锁。
基于这种思想,我们将第一段代码修改如下所示,在创建启动线程之前,先创建一个线程之间竞争使用的Object对象,然后将这个Object对象的引用传递给每一个线程对象的lock成员变量。这样一来,每个线程的lock成员都指向同一个Object对象。我们在run方法中,对lock对象使用synchronzied块进行局部封锁,这样就可以让线程去竞争这个唯一的共享的对象锁,从而实现同步。
代码Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->package com.vista; class MyThread implements java.lang.Runnable
{
private int threadId;
private Object lock;
public MyThread(int id, Object obj)
{
this.threadId = id;
this.lock = obj;
}
@Override
public void run()
{
synchronized(lock)
{
for (int i = 0; i < 100; ++i)
{
System.out.println("Thread ID: " + this.threadId + " : " + i);
}
}
}
}
public class ThreadDemo
{
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException
{
Object obj = new Object();
for (int i = 0; i < 10; ++i)
{
new Thread(new MyThread(i, obj)).start();
Thread.sleep(1);
}
}
}
从第二段代码可知,同步的关键是多个线程对象竞争同一个共享资源即可,上面的代码中是通过外部创建共享资源,然后传递到线程中来实现。我们也可以利用类成员变量被所有类的实例所共享这一特性,因此可以将lock用静态成员对象来实现,代码如下所示:
代码Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->package com.vista; class MyThread implements java.lang.Runnable
{
private int threadId;
private static Object lock = new Object();
public MyThread(int id)
{
this.threadId = id;
}
@Override
public void run()
{
synchronized(lock)
{
for (int i = 0; i < 100; ++i)
{
System.out.println("Thread ID: " + this.threadId + " : " + i);
}
}
}
}
public class ThreadDemo
{
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException
{
for (int i = 0; i < 10; ++i)
{
new Thread(new MyThread(i)).start();
Thread.sleep(1);
}
}
}
再来看第一段代码,实例方法中加入sychronized关键字封锁的是this对象本身,而在静态方法中加入sychronized关键字封锁的就是类本身。静态方法是所有类实例对象所共享的,因此线程对象在访问此静态方法时是互斥访问的,从而可以实现线程的同步,代码如下所示:
代码Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->package com.vista; class MyThread implements java.lang.Runnable
{
private int threadId; public MyThread(int id)
{
this.threadId = id;
}
@Override
public void run()
{
taskHandler(this.threadId);
}
private static synchronized void taskHandler(int threadId)
{
for (int i = 0; i < 100; ++i)
{
System.out.println("Thread ID: " + threadId + " : " + i);
}
}
}
public class ThreadDemo
{
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException
{
for (int i = 0; i < 10; ++i)
{
new Thread(new MyThread(i)).start();
Thread.sleep(1);
}
}
}
作者:洞庭散人
出处:http://phinecos.cnblogs.com/
浅谈Java多线程的同步问题 【转】的更多相关文章
- 转载:浅谈Java多线程的同步问题【很好我就留下来,多分共享】
转载:http://www.cnblogs.com/phinecos/archive/2010/03/13/1684877.html#undefined 多线程的同步依靠的是对象锁机制,synchro ...
- 浅谈 Java 多线程(一) --- JMM
为什么使用多线程 更多的处理器核心数(硬件的发展使 CPU 趋向于更多的核心数,如果不能充分利用,就无法显著提升程序的效率) 更快的响应时间(复杂的业务场景下,会存在许多数据一致性不强的操作,如果将这 ...
- 浅谈Java多线程同步机制之同步块(方法)——synchronized
在多线程访问的时候,同一时刻只能有一个线程能够用 synchronized 修饰的方法或者代码块,解决了资源共享.下面代码示意三个窗口购5张火车票: package com.jikexueyuan.t ...
- 浅谈Java多线程
线程与进程 什么是进程? 当一个程序进入内存中运行起来它就变为一个进程.因此,进程就是一个处于运行状态的程序.同时进程具有独立功能,进程是操作系统进行资源分配和调度的独立单位. 什么是线程? 线程是进 ...
- 浅谈Java多线程中的join方法
先上代码 新建一个Thread,代码如下: package com.thread.test; public class MyThread extends Thread { private String ...
- 浅谈java类集框架和数据结构(2)
继续上一篇浅谈java类集框架和数据结构(1)的内容 上一篇博文简介了java类集框架几大常见集合框架,这一篇博文主要分析一些接口特性以及性能优化. 一:List接口 List是最常见的数据结构了,主 ...
- 浅谈Java线程安全
浅谈Java线程安全 - - 2019-04-25 17:37:28 线程安全 Java中的线程安全 按照线程安全的安全程序由强至弱来排序,我们可以将Java语言中各种操作共享的数据分为以下五类 ...
- 浅谈JAVA集合框架
浅谈JAVA集合框架 Java提供了数种持有对象的方式,包括语言内置的Array,还有就是utilities中提供的容器类(container classes),又称群集类(collection cl ...
- 浅谈Java的集合框架
浅谈Java的集合框架 一. 初识集合 重所周知,Java有四大集合框架群,Set.List.Queue和Map.四种集合的关注点不同,Set 关注事物的唯一性,List 关注事物的索引列表,Q ...
随机推荐
- 【Django】优化小技巧之清除过期session
事情是这样的,大概也就几万注册用户的站点(使用django1.6), session 存储在关系型数据库,这次上线之后发现session表几十万数据了,过期session没有被自动删除 思考 官网 s ...
- Linux0.11小结
第一部分 基础内容 1.操作系统基础 操作系统是计算机硬件系统与用户程序间重要环节,理解操作系统的原理是编写优秀代码的基础.教课书中阐述的操作系统一般由5部分组成. 一个最简单的操作系统,可以 ...
- 【Android 应用开发】 Ubuntu 安装 Android Studio (旧版本|仅作参考)
. 果断换Ubuntu了, Ubuntu的截图效果不好, 不能设置阴影 ... 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article ...
- python标准库:collections和heapq模块
http://blog.csdn.net/pipisorry/article/details/46947833 python额外的数据类型.collections模块和heapq模块的主要内容. 集合 ...
- lvs与haproxy
最近一直在看一些高可用性的负载均衡方案,当然那些f5之类的硬件设备是玩不起也接触不到了.只能看这些for free的开源方案. 目前使用比较多的就是标题中提到的这两者,其实lvs和haproxy都是实 ...
- SpriteBuilder中如何平均拉伸精灵帧动画的距离
首先要在Timeline中选中所有的精灵帧,可以通过如下2种的任意一种办法达成: 1按下Shift键的同时鼠标单击它们 2鼠标在Timeline空白区拖拽直到拉出的矩形包围住所有精灵帧方块后放开鼠标. ...
- RecyclerView notifyItem闪烁的问题
之前我们做点赞,用listview做的话,就是在item实现点击后,写一个scal动画,不过现在都转到RecyclerView,那么要做这种效果于是做了一个notifyItemChanged()的操作 ...
- ERP-非财务人员的财务培训教(二)------如何评价公司/部门经营业绩
一.财务比率分析 第一节 流动性比率 第二节 经营比率 第三节 资本结构比率 第四节 获利能力比率 第五节 现金流量比率 第六节 获现能力比率 二.财务比率金字塔 第二部分 如何评价公 ...
- Leetcode_234_Palindrome Linked List
本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/47334465 Given a singly linked ...
- 初探linux子系统集之led子系统(三)
世界杯结束了,德国战车夺得了大力神杯,阿根廷最终还是失败了.也许3年,5年,或者10年后,人们就不知道巴西世界杯的亚军是谁,但是总是会记得冠军是谁.就像什么考试,比赛,第一永远会被人们所记住,所以我们 ...