娜娜的美好一天▲如何自如权衡线程安全与性能,程序员:时刻保持对代码的思考
【娜娜的美好一天▲如何自如权衡线程安全与性能,程序员:时刻保持对代码的思考】}break如果多线程情况下使用这个类 , 无论多线程如何使用和调度这个类 , 这个类总是表示出正确的行为 , 这个类就是线程安全的 。 类的线程安全表现为:操作的原子性 , 类似数据库事务 。 内存的可见性 , 当前线程修改后其他线程立马可看到 。 不做正确的同步 , 在多个线程之间共享状态的时候 , 就会出现线程不安全 。 1.栈封闭所有的变量都是在方法内部声明的 , 这些变量都处于栈封闭状态 。 方法调用的时候会有一个栈桢 , 这是一个独立的空间 。 在这个独立空间创建跟使用则绝对是安全的 , 但是注意不要返回该变量哦!publicvoidJustTest(){Integera=12Useruser=newUser(12)2.无状态说白了就是这个类没有任何成员变量 , 只有一堆成员函数 , 这样绝对是安全的 。 publicclassStatelessClass{publicintservice(inta,intb){returna*b//...publicvoidt(){}3.类不可变Java中不管是String对象跟基本类型装箱后的对象都是不可变的 , 说白了就是都带有final 。 让状态不可变 , 两种方式:加final关键字 , 对于一个类 , 所有的成员变量应该是私有的 , 同样的只要有可能 , 所有的成员变量应该加上final关键字 , 但是加上final , 要注意如果成员变量又是一个对象时 , 这个对象所对应的类也要是不可变 , 才能保证整个类是不可变的 。 根本就不提供任何可供修改成员变量的地方 , 同时成员变量也不作为方法的返回值,说白了就是不提供任何set方法 。 publicclassImmutableFinalRef{privatefinalintaprivatefinalintbprivatefinalUseruser//这里 , 就不能保证线程安全啦publicImmutableFinalRef(inta,intb){super()this.a=athis.b=bthis.user=newUser(2)publicintgetA(){returnapublicintgetB(){returnbpublicUsergetUser(){returnuserpublicstaticclassUser{privateintage//privatefinalintagepublicUser(intage){this.age=agepublicintgetAge(){returnage}publicvoidsetAge(intage){this.age=age}publicstaticvoidmain(String[]args){ImmutableFinalRefref=newImmutableFinalRef(12,23)Useru=ref.getUser()u.setAge(35)//对象不可变不过对象里的数据也要不可变才可以!保证类的可见性 , 最适合一个线程写 , 多个线程读的情景 , 再重复一遍只保证变量的可见性!用volatile修饰的变量在get的时候多线程情况下不用加锁 , 保证可见性 。 但是在set的时候要加锁或者通过CAS操作进行变化 。 比如ConcurrentHashMap 。 
文章图片
前面的若干章节都写过对于操作变量用syn,lock,CAS 。 类中持有的成员变量 , 特别是对象的引用 , 如果这个成员对象不是线程安全的 , 通过get等方法发布出去(return出去) , 会造成这个成员对象本身持有的数据在多线程下不正确的修改 , 从而造成整个类线程不安全的问题 。 解决方法:publicclassUnsafePublish{//要么用线程的容器替换 , 要么发布出去的时候 , 提供副本 , 深度拷贝privateList<Integer>list=newArrayList<>(3)publicUnsafePublish(){list.add(1)list.add(2)list.add(3)//将list不安全的发布出去了publicList<Integer>getList(){returnlist}//也是安全的,加了锁publicsynchronizedintgetList(intindex){returnlist.get(index)publicsynchronizedvoidset(intindex,intval){list.set(index,val)底层类似跟一个HashMap一样简单理解 , key=线程 , value就是当前线程使用的变量 。 死锁竞争的资源一定是多于1个 , 同时小于等于竞争的线程数 , 资源只有一个 , 只会产生激烈的竞争 。 死锁的根本成因:获取锁的顺序不一致导致 。 publicclassNormalDeadLock{privatestaticObjectvalueFirst=newObject()//第一个锁privatestaticObjectvalueSecond=newObject()//第二个锁//先拿第一个锁 , 再拿第二个锁privatestaticvoidfisrtToSecond()throwsInterruptedException{throwsInterruptedException{StringthreadName=Thread.currentThread().getName()synchronized(valueFirst){System.out.println(threadName+"获得第一个")TimeUnit.MILLISECONDS.sleep(100)synchronized(valueSecond){System.out.println(threadName+"获得第二个")//先拿第二个锁 , 再拿第一个锁privatestaticvoidSecondToFisrt()throwsInterruptedException{//执行先拿第二个锁 , 再拿第一个锁privatestaticclassTestThreadextendsThread{privateStringnamepublicTestThread(Stringname){this.name=namepublicvoidrun(){Thread.currentThread().setName(name)try{SecondToFisrt()}catch(InterruptedExceptione){e.printStackTrace()Thread.currentThread().setName("TestDeadLock")TestThreadtestThread=newTestThread("SubTestThread")testThread.start()fisrtToSecond()//先拿第一个锁 , 再拿第二个锁如果怀疑发送死锁:
推荐阅读
- 「iPhone 8」iPhone再遇续航危机?学会这几招,一天不充不是梦
- 爱搞笑的鸡大腿作为男人,我必须成人之美!,【笑话】:为了不破坏这美好的瞬间
- 史上蝉蜀汉能统一天下吗?,三国中如果关羽没有走麦城
- 小梦狂说事踩油门就走?很多车主不懂,汽车暴晒一天
- 美好呈现加盟美容店的经营者一定要注意这几个问题
- 娱乐新潮向欧阳娜娜的字迹,看到赵今麦:真是字如其人!,关晓彤的字迹
- 井瞥乃u不带重样的,出租房里你遇到过哪些奇葩事?网友:一天换一个男友
- 前方高能李现杨紫友情客串,胡一天成最强男主,《亲爱的亲爱的2》即将开拍
- 娜娜手机领域买手机到底是买个自己喜欢的?还是买个别人喜欢的?
- 『埃里克森』今夏吉格斯再向曼联强推一天才,这次是他……
