修饰静态方法默认获取当前class的锁,同步方法没有释放的锁,不影响class其他非同步方法的调用,也不影响不同锁的同步方法,更不影响使用class的其他属性.

package thread.base.sync;

import java.util.concurrent.TimeUnit;

/**
*
* @author ZhenWeiLai
*
*/
public class A { synchronized public static void saySomething() throws InterruptedException{
//前后可以写非同步代码
synchronized(A.class){
System.out.println("a");
TimeUnit.SECONDS.sleep(5);
}
//前后可以写非同步代码
} // /**
// * 与上面相等(但是方法内没有非同步区域):可以这么理解,把synchronized当修饰符用总不能写成synchronized(A.claa) public static void saySomething()
// * 这是静态方法啊,不需要实例就可以调用,那么我获取什么锁啊?只能获取本class的锁吖,你又不能给我传参
// */
// synchronized public static void saySomething() throws InterruptedException{
// System.out.println("a");
// TimeUnit.SECONDS.sleep(5);
// }
}

修饰非静态方法,默认获取调用此方法的实例对象锁    Spring容器管理的bean默认都是单例的(当然可以注解为prototype),所以加上 synchronized 的方法,注解自动装配获取的实例,调用都会同步了

package thread.base.sync;

import java.util.concurrent.TimeUnit;

/**
*
* @author ZhenWeiLai
*
*/
public class A { public void saySomething() throws InterruptedException {
//前面可以写非同步代码
synchronized (this) {
System.out.println("a");
TimeUnit.SECONDS.sleep(5);
}
//后面可以写非同步代码
} // /**
// * 与上面相等,看了静态的,再看对象方法更好理解.
// * 必须要有实例才能调用吧?太好办了那么我就获取当前实例对象的锁
// */
// synchronized public void saySomething() throws InterruptedException{
// System.out.println("a");
// TimeUnit.SECONDS.sleep(5);
// }
}

synchronized (object)与synchronized (this)一样,获取实例对象的锁.因为synchronized (this)只能获取当前实例锁,那么synchronized (object)就是可以获取其他实例锁的意思

对于synchronized 最简单粗暴的理解就是,你要哪些线程方法同步,就跟他们获取一样的锁好了,A.class,就获取A.class,  objectA 就获取 objectA(我说的不是对象名相同,而是真真切切在java堆中的同一个对象),

据说ConcurrentHashMap 就是用16个对象锁实现的

我也模拟一下

package thread.base.sync.hashmap;

import java.util.HashMap;
import java.util.concurrent.TimeUnit; /**
*
* @author ZhenWeiLai 模拟16个并发的线程安全put
* @param <K>
* @param <V>
*/
public class SyncHashMap<K, V> extends HashMap<K, V> {
/**
*
*/
private static final long serialVersionUID = 4071859310703431745L; // 初始化16个对象锁
Object[] lock = new Object[16]; public SyncHashMap() {
for (int i = 0; i < 16; i++) {
lock[i] = new Object();
}
} /**
* 线程安全方法
*
* @param key
* @param value
* @return
* @throws InterruptedException
*/
public V safePut(K key, V value) throws InterruptedException {
/**
* 不一样的key有可能得到一样的余数,据说hashcode算法问题.我这里是取巧,不深究
* 万一两个不同的key得到一样的余数,那么慢的一个就要等待5秒咯
* 随机获取16个对象锁中的一个
*/
synchronized (lock[key.hashCode() % 16]) {
System.out.println("aaaa");
TimeUnit.SECONDS.sleep(5);
// 同步调用原生put方法
return super.put(key, value);
}
} }

测试方法,两个key相同,其中获取锁慢的那个线程会等5秒再输出控制台

package thread.base.sync.hashmap;

/**
*
* @author ZhenWeiLai
*
*/
public class TestClass {
public static void main(String[] args) {
SyncHashMap<Integer,Integer> shm = new SyncHashMap<>();
new Thread(()->{
try {
//两个线程操作同一个key,
shm.safePut(1, 1);
} catch (Exception e) {
e.printStackTrace();
}
}).start(); new Thread(()->{
try {
//两个线程操作同一个key
shm.safePut(1,1);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}

试着简单易懂记录synchronized this object Class的区别,模拟ConcurrentHashMap的更多相关文章

  1. HashSet的实现原理,简单易懂

    HashSet的实现原理,简单易懂   答: HashSet实际上是一个HashMap实例,都是一个存放链表的数组.它不保证存储元素的迭代顺序:此类允许使用null元素.HashSet中不允许有重复元 ...

  2. 如果简单的记录,就可以为这个世界创造更多的财富,那么还有什么理由不去写博客呢? — 读<<黑客与画家>> 有感

    上一次博文发文时间是2016.1.15,7个月已经过去了.最近读了一本<>的书,对我触动挺大的!里面有关于技术趋势的探讨,也有关于人生和财富的思考! 开始更新iOS122的文章的初衷是,聚 ...

  3. Python简单爬虫记录

    为了避免自己忘了Python的爬虫相关知识和流程,下面简单的记录一下爬虫的基本要求和编程问题!! 简单了解了一下,爬虫的方法很多,我简单的使用了已经做好的库requests来获取网页信息和Beauti ...

  4. redis5.0.3单实例简单安装记录

    redis5.0.3单实例简单安装记录 日常需要测试使用,索性记录下来,免得临时又麻烦的找资料. yum -y install make gcc-c++ cmake bison-devel ncurs ...

  5. 【repost】让你一句话理解闭包(简单易懂)

    接触javascript很久了,每次理解闭包都似是而非,最近在找Web前端的工作,所以需要把基础夯实一下. 本文是参照了joy_lee的博客 闭包 在她这篇博客的基础上以批注的形式力争把我的理解阐述出 ...

  6. 5、Cocos2dx 3.0游戏开发找小三之測试例子简单介绍及小结

    重开发人员的劳动成果.转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27186557 測试例子简单介绍 Cocos2d-x ...

  7. Oracle触发器简单入门记录

    写在前面: 最近,老项目新增了日报优化的需求,丽姐让我用触发器去实现当数据插入或者更新的时候,实现对日报表数据更新操作.嗯嗯嗯呢,之前学习数据库的时候,有碰到过触发器,但都是一跳而过,也没怎么去真正的 ...

  8. 27:简单错误记录SimpleErrorLog

    题目描述 开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号. 处理: 1. 记录最多8条错误记录,循环记录,对相同的错误记录(净文件名称和行号完全匹配)只记录一条,错误计数增加: ...

  9. 【转】JS回调函数--简单易懂有实例

    JS回调函数--简单易懂有实例 初学js的时候,被回调函数搞得很晕,现在回过头来总结一下什么是回调函数. 我们先来看看回调的英文定义:A callback is a function that is ...

随机推荐

  1. JVM 自动内存管理:对象判定和回收算法

  2. base64_encode与base64_decode

    base64_encode 编辑 本词条缺少名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! base64_encode() returns 使用 base64 对 data 进行编码. ...

  3. 定时任务schedule(spring boot )

    1. 定时任务实现方式:SpringBoot自带的Scheduled,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多,本文主要介绍. 执行方式:单线程(串行)多线程(并行) ...

  4. CSS——类和ID选择器的区别

    1.相同点,可以应用在任何元素. 2.不同点,ID选择器只能在元素里只能分别引用,不能同时引用. 如: <style type="text/css">.stress{( ...

  5. 图说:为什么Java中的字符串被定义为不可变的

    8张图,看懂Java字符串的不变性 字符串,想必大家最熟悉不过了,通常我们在代码中有几种方式可以创建字符串,比如:String s = "Hollis";这时,其实会在堆内存中创建 ...

  6. BZOJ 2694: Lcm [莫比乌斯反演 线性筛]

    题意:求\(\sum\limits_{i=1}^n \sum\limits_{j=1}^m lcm(i,j)\ : gcd(i,j) 是sf 无平方因子数\) 无平方因子数?搞一个\(\mu(gcd( ...

  7. HDU 5996 dingyeye loves stone [阶梯Nim]

    dingyeye喜欢和你玩石子游戏. dingyeye有一棵nn个节点的有根树,节点编号为00到n−1n−1,根为00号节点.游戏开始时,第ii个节点上有a[i]a[i]个石子.两位玩家轮流操作,每次 ...

  8. HDU 3944 DP? [Lucas定理 诡异的预处理]

    DP? Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 128000/128000 K (Java/Others)Total Subm ...

  9. Hibernate之HelloWorld

    1. 步骤 0. 导入相关Jar包. 1. 编写Hibernate的持久化文件 (默认为hibernate.cfg.xml). 2. 编写持久化类. 3. 创建对象 - 关系文件(.htm.xml文件 ...

  10. php+redis 学习 六 订阅

    <?php header('content-type:text/html;chaeset=utf-8'); /** * redis实战 * * 订阅 * * @example php subsc ...