线程安全 1

本文深入探讨了线程安全的概念及其实现方法,包括栈封闭、不可变性、volatile关键字的使用、加锁机制以及ThreadLocal的应用等。

课程素材来自 http://enjoy.ke.qq.com/    版权所有

什么是线程安全

如果多个线程访问并使用这个类,这类总是表现线程安全的,那么这个类就是线程安全的。

类的线程安全表现为:

l  操作的原子性

l  内存的可见性

不做正确的同步,在多个线程之间共享状态的时候,就会出现线程不安全。

怎么做到线程安全

栈封闭

所有的变量都在方法内部声明的,这些状态都处于栈封闭状态。

示例代码:



无状态的类

     没有任何成员变量的类,就叫无状态的类

package com.hw.ch9;
public class Stateless {
    public String  result() {
        return "success";
    }
}


让类不可变

让状态不可变,两种方式:

1,加final关键字,对于一个类,所有的成员变量应该是私有的,同样的只要有可能,所有的成员变量应该加上final关键字,

但是加上final,要注意如果成员变量又是一个对象时,这个对象所对应的类也要是不可变,才能保证整个类是不可变的。

public class ImmutableFinal {
    private  final  int a;
    private  final  int b;
    public  ImmutableFinal(int a, int b){
        this.a=a;
        this.b=b;
    }
    public int getA() {
        return a;
    }

    public int getB() {
        return b;
    }
}

2、根本就不提供任何可供修改成员变量的地方,同时成员变量也不作为方法的返回值

public class ImmutableFinalRef {
    private  final  int a;
    private  final  int b;
    private  final  User  user;
    public ImmutableFinalRef(int a, int b,User  user){
        this.a=a;
        this.b=b;
        this.user  = user;
    }
    public int getA() {
        return a;
    }

    public int getB() {
        return b;
    }

    public  static  class  User{
        private int  age;
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
    }
这样的也是不安全的操作,因为别个的线程可以获取到user对象的引用,可以改变user的值,但是,把
   user对象的代码改成这样  
    public    class  User{
//        private int  age;
        private  final int  age;
        public  User(int  age){
            this.age  = age;
        }
        public int getAge() {
            return age;
        }
//        public void setAge(int age) {
//            this.age = age;
//        }
    }
线程就安全了,因为没有修改的方法了。


volalite

保证类的可见性,最适合一个线程写,多个线程读的情景


加锁和cas

安全的发布

类中持有的成员变量,特别是对象的引用,如果这个成员对象不是线程安全的,
通过get等方法发布出去,会造成这个成员对象本身持有的数据在多线程下不正确的
修改,从而造成整个类线程不安全的问题。

ThreadLocal
多个线程变量安全

下载方式:https://pan.quark.cn/s/a4b39357ea24 布线问题(分支限界算法)是计算机科学和电子工程领域中一个广为人知的议题,它主要探讨如何在印刷电路板上定位两个节点间最短的连接路径。 在这一议题中,电路板被构建为一个包含 n×m 个方格的矩阵,每个方格能够被界定为可通行或不可通行,其核心任务是定位从初始点到最终点的最短路径。 分支限界算法是处理布线问题的一种常用策略。 该算法与回溯法有相似之处,但存在差异,分支限界法仅需获取满足约束条件的一个最优路径,并按照广度优先或最小成本优先的原则来探索解空间树。 树 T 被构建为子集树或排列树,在探索过程中,每个节点仅被赋予一次成为扩展节点的机会,且会一次性生成其全部子节点。 针对布线问题的解决,队列式分支限界法可以被采用。 从起始位置 a 出发,将其设定为首个扩展节点,并将与该扩展节点相邻且可通行的方格加入至活跃节点队列中,将这些方格标记为 1,即从起始方格 a 到这些方格的距离为 1。 随后,从活跃节点队列中提取队首节点作为下一个扩展节点,并将与当前扩展节点相邻且未标记的方格标记为 2,随后将这些方格存入活跃节点队列。 这一过程将持续进行,直至算法探测到目标方格 b 或活跃节点队列为空。 在实现上述算法时,必须定义一个类 Position 来表征电路板上方格的位置,其成员 row 和 col 分别指示方格所在的行和列。 在方格位置上,布线能够沿右、下、左、上四个方向展开。 这四个方向的移动分别被记为 0、1、2、3。 下述表格中,offset[i].row 和 offset[i].col(i=0,1,2,3)分别提供了沿这四个方向前进 1 步相对于当前方格的相对位移。 在 Java 编程语言中,可以使用二维数组...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值