[转]关于java中的 sychronized 同步方法 与 同步块的理解
首先,需要说明一点,也是最重要的一点,无论是同步方法 还是 同步块 都是只针对同一个对象的多线程而言的,只有同一个对象产生的多线程,才会考虑到 同步方法 或者是 同步块,如果定义多个实例的同步,可以考虑使用mutex,创建类似于c++整个服务全局锁,或者创建一个全局单例类,在其内定义全局锁。比如以下的代码片段定义线程同步无任何意义:
public class Test1 implements Runnable {
public void run() {
synchronized(this) {
try {
System.out.println(System.currentTimeMillis());
Thread.sleep(2000);
System.out.println(System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
for(int i=0;i<10;i++) {
new Thread(new Test1()).start(); // 关键,如果将 new Test1拿到外面,那么同步方法才有意义,如下:
//public static void main(String[] args) {
// Test1 test=new Test1();
// for(int i=0;i<10;i++) {
// new Thread(test).start();
} } }
因为java或者C#中的线程同步与多线程的概念,只是在单个对象下 这一范围内的,也就是说:单个对象下的 多线程同步 或者 死锁。如果有下面的需求:
1,该类只允许在同一时刻实例化(new)一次;----考虑单例模式
2,或者只允许在同一时刻仅可存活一个对于数据库的修改 或 删除操作;--考虑单例模式 或者 数据库内的事务锁概念。
-----------------------------------------------------
下面我们着重介绍java中的 Sychronized的用法,具体为:同步方法 与 同步块
synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。
1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:
public synchronized void accessVal(int newVal);
synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。
synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为 synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供了更好的解决办法,那就是 synchronized 块。
2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:
synchronized(syncObject) {
//允许访问控制的代码
}
synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。
对synchronized(this)的一些理解
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用
------------------------------------------------------------------------
网上还有很多关于java中的Sychronized的个人理解与总结,可以忘记的时候看看,但是上面的东东是核心,切记。
此外最关键的,线程同步会耗费很多性能,所以如无必要,尽量少用线程同步,如果使用最好使用同步块而不要使用同步方法。
[转]关于java中的 sychronized 同步方法 与 同步块的理解的更多相关文章
- Java中wait()方法为什么要放在同步块中?(lost wake-up 问题)
问题起源 事情得从一个多线程编程里面臭名昭著的问题"Lost wake-up problem"说起. 这个问题并不是说只在Java语言中会出现,而是会在所有的多线程环境下出现. 假 ...
- Java中使用CountDownLatch进行多线程同步
CountDownLatch介绍 在前面的Java学习笔记中,总结了Java中进行多线程同步的几个方法: 1.synchronized关键字进行同步. 2.Lock锁接口及其实现类ReentrantL ...
- Java中“指针”的解释以及对“引用”的理解
Java中"指针"的解释以及对"引用"的理解 初学Java面对对象编程,对于一些概念还真的有点难以理解,主要是因为不由自主的联系到以前学过的C语言知识,时不时的 ...
- Java并发编程:Java中的锁和线程同步机制
锁的基础知识 锁的类型 锁从宏观上分类,只分为两种:悲观锁与乐观锁. 乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新 ...
- Java中String、StringBuffer、StringBuilder区别与理解
一.先比较String.StringBuffer.StringBuilder变量的HashCode值 使用System.out.println(obj.hashcode())输出的时对象的哈希码, 而 ...
- Java中String做为synchronized同步锁使用详解
Java中使用String作同步锁 在Java中String是一种特殊的类型存在,在jdk中String在创建后是共享常量池的,即使在jdk1.8之后实现有所不同,但是功能还是差不多的. 借助这个特点 ...
- Java中static的用法,初始化块
使用 Arrays 类操作 Java 中的数组语法: Arrays.sort(数组名); 可以使用 sort( ) 方法实现对数组的排序,只要将数组名放在 sort( ) 方法的括号中,就可以完成对该 ...
- java中静态变量,静态代码块,静态方法,实例变量,匿名代码块等的加载顺序
转自:http://blog.csdn.net/mrzhoug/article/details/51581994 一.在Java中,使用”{}”括起来的代码称为代码块,代码块可以分为以下四种: 1.普 ...
- Java中的继承、封装、多态的理解
Java中的继承.封装.多态 继承的理解: 1.继承是面向对象的三大特征之一,也是实现代码复用的重要手段.Java的继承具有单继承的特点,每个子类只有一个直接父类. 2.Java的继承通过extend ...
随机推荐
- 重载VerifyRenderingInServerForm
重载VerifyRenderingInServerForm 今天在做一个AjaxPro的应用时,VerifyRenderingInServerForm给我带来了麻烦,在网上找了找,发现大多数人的解决方 ...
- Git遇到的一点错误
[背景] 折腾: [记录]将googlecode上面的crifanLib迁移到Github上 期间出错: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1 ...
- BZOJ3439: Kpm的MC密码
3439: Kpm的MC密码 Time Limit: 15 Sec Memory Limit: 256 MBSubmit: 166 Solved: 79[Submit][Status] Descr ...
- Scala:(2)控制结构
(1)if else val s=) else -1 (2)循环 ){ r=r*n n-= } ///for 循环 to n) r=r*i //until val s="Hello" ...
- (转载)用PHP实现翻页
(转载)http://blog.csdn.net/emili/article/details/5221744 原文参考http://www.cnblogs.com/xxcainiao/archive/ ...
- Linux学习笔记30——套接字
一 什么是套接字 套接字是一种通信机制,凭借这种机制,客户/服务器系统的开发既可以在本地单机上进行,也可以跨网络进行. 二 套接字属性 套接字的特性由3个属性确定,它们是:域,类型和协议 1 套接 ...
- 解决外部机器通过VM内ubuntu IP 无法访问vm内web服务的问题
1. 2.i root@ubuntu:/home/udapeng# ifconfig root@ubuntu:/www/sentry# nano uwsgi.ini root@ubuntu:/www/ ...
- 《A First Course in Probability》-chaper3-条件概率和独立性-基本公式
EX1: 乔伊80%肯定他把失踪的钥匙放在了他外套两个口袋中的一个.他40%确定放在左口袋,40%确定放在右口袋.如果检查了左口袋发现没有找到钥匙,那么钥匙在右口袋的条件概率是多少? 分析:很基本的条 ...
- dp poj 1080 Human Gene Functions
题目链接: http://poj.org/problem?id=1080 题目大意: 给两个由A.C.T.G四个字符组成的字符串,可以在两串中加入-,使得两串长度相等. 每两个字符匹配时都有个值,求怎 ...
- Unity3D开发类似保龄球游戏
先学习一些基本的脚本实现: 1.动态创建物体.默认位置是(0,0)位置 GameObject goNew = GameObject.CreatePrimitive(PrimitiveType.Cube ...