5

[if !supportLists]1[endif]附录

[if !supportLists]1.1[endif]减少同步块范围

public boolean userHasAdminAccess(StringuserName) {

synchronized (attributesMap) {

String rights = attributesMap.get("users." + userName +".accessRights");

if (rights == null)

return false;

else

return (rights.indexOf("ADMIN") >= 0);

}

}

为创建串联的字符串“users.brian.accessRights”,编译器将创建一个临时的StringBuffer对象,调用StringBuffer.append三次,然后调用StringBuffer.toString,这意味着至少两个对象的创建和几个方法调用。接着,程序将调用HashMap.get检索该字符串,然后调用String.indexOf抽取想要的权限标识符。

public boolean userHasAdminAccess(StringuserName) {

String key = "users." + userName + ".accessRights";

String rights;

synchronized (attributesMap) {

rights = attributesMap.get(key);

}

return ((rights != null)

&& (rights.indexOf("ADMIN") >= 0));

}

需要注意StringBuffer是否为线程安全操作?

[if !supportLists]1.1[endif]减少锁粒度

public class AttributesStore {

private HashMap usersMap = new HashMap();

private HashMap servicesMap = new HashMap();

public synchronized void setUserInfo(String user, UserInfo userInfo) {

usersMap.put(user, userInfo);

}

public synchronized UserInfo getUserInfo(String user) {

return usersMap.get(user);

}

publicsynchronized void setServiceInfo(String service, ServiceInfo serviceInfo) {

servicesMap.put(service, serviceInfo);

}

public synchronized ServiceInfo getServiceInfo(String service) {

return servicesMap.get(service);

}

如果一个线程正在执行setUserInfo,不仅仅其它线程将被锁在setUserInfo和getUserInfo外面(这是我们希望的),而且这些线程也被锁在getServiceInfo和setServiceInfo外面。

public class AttributesStore {

private HashMap usersMap = new HashMap();

private HashMap servicesMap = new HashMap();

public void setUserInfo(String user, UserInfo userInfo) {

synchronized(usersMap) {

usersMap.put(user, userInfo);

}

}

public UserInfo getUserInfo(String user) {

synchronized(usersMap) {

return usersMap.get(user);

}

}

public void setServiceInfo(String service, ServiceInfo serviceInfo) {

synchronized(servicesMap) {

servicesMap.put(service, serviceInfo);

}

}

public ServiceInfo getServiceInfo(String service) {

synchronized(servicesMap) {

return servicesMap.get(service);

}

}

}

[if !supportLists]1.1[endif]信号量

如果多个线程需要访问数目很少的资源,可以使用信号量计数。将一个信号量初始化为可获得的资源数量。一旦某个线程获得了信号量,可获得的资源数减一。线程消耗完资源并释放该资源时,计数器就会加一。当信号量控制的所有资源都已被占用时,若有线程试图访问此信号量,则会进入阻塞状态,直到有可用资源被释放。

class Semaphore {

private int count;

public Semaphore(int n) {

this.count = n;

}

public synchronized void acquire() {

while(count == 0) {

try {

wait();

} catch (InterruptedException e) {

//keep trying

}

}

count--;

}

public synchronized void release() {

count++;

notify(); //alert a thread that's blocking on this semaphore

}

}

[if !supportLists]1.1[endif]什么是可见性

在一个单线程程序中,如果首先改变一个变量的值,再读取该变量的值的时候,所读取到的值就是上次写操作写入的值。也就是说前面操作的结果对后面的操作是肯定可见的。但是在多线程程序中,如果不使用一定的同步机制,就不能保证一个线程所写入的值对另外一个线程是可见的。造成这种情况的原因可能有下面几个:

[if !supportLists]l[endif]CPU内部的缓存:现在的CPU一般都拥有层次结构的几级缓存。CPU直接操作的是缓存中的数据,并在需要的时候把缓存中的数据与主存进行同步。因此在某些时刻,缓存中的数据与主存内的数据可能是不一致的。某个线程所执行的写入操作的新值可能当前还保存在CPU的缓存中,还没有被写回到主存中。这个时候,另外一个线程的读取操作读取的就还是主存中的旧值。

[if !supportLists]l[endif]CPU的指令执行顺序:在某些时候,CPU可能改变指令的执行顺序。这有可能导致一个线程过早的看到另外一个线程的写入操作完成之后的新值。

[if !supportLists]l[endif]编译器代码重排:出于性能优化的目的,编译器可能在编译的时候对生成的目标代码进行重新排列。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,622评论 18 399
  • 5.1 同步容器类 同步容器类包括Vector和HashTable以及Collection.synchronize...
    大海孤了岛阅读 396评论 1 0
  • 大家好,我是今天的老师——信手弧来。今天由我给大家讲讲如何培养理财习惯。 首先,预算、记账及分析。 大家都知道,记...
    信手弧来阅读 114评论 0 0
  • 周末带女儿来朋友家玩,朋友家里的小男子汉比女儿大一岁,两个小孩子玩的相当和谐,连吵嘴都不曾发生过一句,两个人公主王...
    王彤2017阅读 305评论 1 2
  • 每一年我都会给自己定几个关键词,这一年也围绕着他们而展开。今年我的关键词有三个:养气、分享、陪伴家人 1.养气 2...
    刘欢_Yoyo阅读 440评论 2 1