java并发编程之线程安全

java并发编程之线程安全,第1张

一、什么是线程安全

线程安全是多线程编程时的计算机程序代码中的一个概念。. 在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。

同一个资源,多个线程 *** 作它的状态,会发生结果和期望不一致的情况.

二、举例

import lombok.Data;

@Data
public class UnsafeSwquence {
    private int value;

    public int getNest(){
        //value自增
        value++;
        //答应打印当前线程的名称及值
        System.out.println(Thread.currentThread().getName()+":"+value);
        return value;
    }
}
1、单线程 *** 作

结果总是100

 /**
     * 单线程
     */
    @Test
    void test01() {
        UnsafeSwquence unsafeSwquenc = new UnsafeSwquence();
        for (int i = 0; i < 100; i++) {
            unsafeSwquenc.getNest();
        }
        System.out.println(unsafeSwquenc.getValue());
    }
main:1
main:2
main:3
main:4
main:5
main:6
main:7
main:8
main:9
main:10
main:11
main:12
main:13
main:14
main:15
main:16
main:17
main:18
main:19
main:20
main:21
main:22
main:23
main:24
main:25
main:26
main:27
main:28
main:29
main:30
main:31
main:32
main:33
main:34
main:35
main:36
main:37
main:38
main:39
main:40
main:41
main:42
main:43
main:44
main:45
main:46
main:47
main:48
main:49
main:50
main:51
main:52
main:53
main:54
main:55
main:56
main:57
main:58
main:59
main:60
main:61
main:62
main:63
main:64
main:65
main:66
main:67
main:68
main:69
main:70
main:71
main:72
main:73
main:74
main:75
main:76
main:77
main:78
main:79
main:80
main:81
main:82
main:83
main:84
main:85
main:86
main:87
main:88
main:89
main:90
main:91
main:92
main:93
main:94
main:95
main:96
main:97
main:98
main:99
main:100
100
 2、多线程 *** 作

结果概率出现其他值

 /**
     * 多线程
     * @throws InterruptedException
     */
    @Test
    void test02() throws InterruptedException {
        UnsafeSwquence unsafeSwquence = new UnsafeSwquence();
        for (int i = 0; i < 100; i++) {
            //创建线程并启动
            new Thread(() -> {
                unsafeSwquence.getNest();
            }).start();
        }
        //等待线程自增结束
        Thread.sleep(1000);
        //打印自增结果
        System.out.println(unsafeSwquence.getValue());
    }
Thread-1:1
Thread-2:2
Thread-9:3
Thread-4:4
Thread-5:5
Thread-7:6
Thread-3:7
Thread-10:8
Thread-11:9
Thread-13:11
Thread-12:10
Thread-6:13
Thread-14:13
Thread-16:15
Thread-26:14
Thread-27:16
Thread-17:17
Thread-18:18
Thread-19:19
Thread-34:20
Thread-35:21
Thread-22:22
Thread-23:23
Thread-24:24
Thread-38:25
Thread-15:26
Thread-8:27
Thread-29:28
Thread-31:29
Thread-41:34
Thread-25:35
Thread-21:40
Thread-45:33
Thread-30:32
Thread-43:31
Thread-28:30
Thread-42:31
Thread-44:45
Thread-46:44
Thread-32:43
Thread-33:42
Thread-20:41
Thread-40:39
Thread-36:39
Thread-37:38
Thread-39:38
Thread-50:49
Thread-49:48
Thread-48:47
Thread-47:46
Thread-53:52
Thread-52:51
Thread-51:50
Thread-54:53
Thread-56:54
Thread-55:55
Thread-57:56
Thread-59:58
Thread-58:57
Thread-61:60
Thread-62:61
Thread-60:59
Thread-72:66
Thread-66:65
Thread-65:64
Thread-77:70
Thread-64:63
Thread-63:62
Thread-67:71
Thread-76:69
Thread-70:68
Thread-75:74
Thread-68:67
Thread-74:73
Thread-73:72
Thread-69:75
Thread-71:76
Thread-78:77
Thread-80:78
Thread-81:79
Thread-83:80
Thread-84:82
Thread-82:81
Thread-79:83
Thread-85:84
Thread-87:85
Thread-88:86
Thread-89:87
Thread-86:88
Thread-90:90
Thread-92:91
Thread-91:90
Thread-93:92
Thread-96:93
Thread-95:94
Thread-94:95
Thread-97:96
Thread-98:97
Thread-100:98
Thread-99:99
99
三、如何保证线程安全

java并发编程实战给的三种修复方式

1 不在线程之间共享改状态变量;

2 将状态变量修改为不可变的变量;

3 在访问状态变量时使用同步;
1、使用同步状态量,需改getNest方法,添加synchronized关键字(不推荐,性能不佳).
   public synchronized int getNest() {
        //value自增
        value++;
        //打印当前线程的名称及值
        System.out.println(Thread.currentThread().getName() + ":" + value);
        return value;
    }

 再次执行test02

Thread-1:1
Thread-2:2
Thread-9:3
Thread-4:4
Thread-6:5
Thread-5:6
Thread-7:7
Thread-8:8
Thread-10:9
Thread-12:10
Thread-3:11
Thread-11:12
Thread-14:13
Thread-13:14
Thread-16:15
Thread-17:16
Thread-29:17
Thread-30:18
Thread-20:19
Thread-33:20
Thread-22:21
Thread-23:22
Thread-24:23
Thread-25:24
Thread-26:25
Thread-15:26
Thread-27:27
Thread-28:28
Thread-44:29
Thread-45:30
Thread-19:31
Thread-18:32
Thread-37:33
Thread-48:34
Thread-38:35
Thread-49:36
Thread-39:37
Thread-40:38
Thread-32:39
Thread-41:40
Thread-53:41
Thread-42:42
Thread-54:43
Thread-43:44
Thread-46:45
Thread-47:46
Thread-52:47
Thread-31:48
Thread-51:49
Thread-57:50
Thread-50:51
Thread-58:52
Thread-34:53
Thread-21:54
Thread-59:55
Thread-60:56
Thread-36:57
Thread-35:58
Thread-63:59
Thread-62:60
Thread-61:61
Thread-56:62
Thread-55:63
Thread-65:64
Thread-64:65
Thread-67:66
Thread-66:67
Thread-68:68
Thread-69:69
Thread-70:70
Thread-71:71
Thread-72:72
Thread-74:73
Thread-73:74
Thread-75:75
Thread-76:76
Thread-77:77
Thread-78:78
Thread-79:79
Thread-81:80
Thread-80:81
Thread-82:82
Thread-83:83
Thread-84:84
Thread-85:85
Thread-86:86
Thread-87:87
Thread-88:88
Thread-89:89
Thread-91:90
Thread-90:91
Thread-92:92
Thread-93:93
Thread-94:94
Thread-95:95
Thread-96:96
Thread-97:97
Thread-98:98
Thread-99:99
Thread-100:100
100
2、使用原子类进行计数(推荐)

jdk提供的原子类

import java.util.concurrent.atomic.AtomicInteger;

@Data
public class UnsafeSwquence {
    private int value;
    private AtomicInteger num = new AtomicInteger(0);

    public synchronized int getNest() {
        //value自增
        value++;
        //打印当前线程的名称及值
        System.out.println(Thread.currentThread().getName() + ":" + value);
        return value;
    }

    public int getNestInteger() {
        //num
        num.incrementAndGet();
        //打印当前线程的名称及值
        System.out.println(Thread.currentThread().getName() + ":" + num.get());
        return num.get();
    }
}

测试

 /**
     * 多线程
     * @throws InterruptedException
     */
    @Test
    void test03() throws InterruptedException {
        UnsafeSwquence unsafeSwquence = new UnsafeSwquence();
        for (int i = 0; i < 100; i++) {
            //创建线程并启动
            new Thread(() -> {
                unsafeSwquence.getNestInteger();
            }).start();
        }
        //等待线程自增结束
        Thread.sleep(1000);
        //打印自增结果
        System.out.println(unsafeSwquence.getNum().get());
    }

Thread-1:1
Thread-2:2
Thread-3:3
Thread-4:4
Thread-5:5
Thread-6:6
Thread-7:7
Thread-8:8
Thread-9:9
Thread-10:10
Thread-11:11
Thread-13:12
Thread-12:13
Thread-14:14
Thread-15:15
Thread-16:16
Thread-17:17
Thread-18:18
Thread-19:19
Thread-20:20
Thread-21:21
Thread-22:22
Thread-23:23
Thread-24:24
Thread-25:25
Thread-27:26
Thread-26:27
Thread-29:28
Thread-31:29
Thread-30:30
Thread-28:31
Thread-33:32
Thread-32:33
Thread-35:34
Thread-34:35
Thread-37:36
Thread-39:37
Thread-36:38
Thread-40:39
Thread-38:40
Thread-42:41
Thread-41:42
Thread-44:43
Thread-43:44
Thread-46:45
Thread-47:46
Thread-45:47
Thread-48:48
Thread-50:49
Thread-49:50
Thread-51:51
Thread-52:52
Thread-53:53
Thread-54:54
Thread-55:55
Thread-56:56
Thread-57:57
Thread-58:58
Thread-59:59
Thread-60:60
Thread-61:61
Thread-62:62
Thread-63:63
Thread-64:64
Thread-65:65
Thread-66:66
Thread-67:67
Thread-68:68
Thread-69:69
Thread-70:70
Thread-71:71
Thread-72:72
Thread-73:73
Thread-74:74
Thread-76:75
Thread-75:76
Thread-77:77
Thread-79:78
Thread-78:79
Thread-81:80
Thread-82:81
Thread-80:82
Thread-83:83
Thread-84:84
Thread-85:85
Thread-86:86
Thread-87:87
Thread-88:88
Thread-89:89
Thread-90:90
Thread-91:91
Thread-93:92
Thread-94:93
Thread-95:94
Thread-92:95
Thread-96:96
Thread-97:97
Thread-98:98
Thread-100:99
Thread-99:100
100

示例用到的依赖

    
            org.projectlombok
            lombok
            1.18.24
        
        
            org.junit.jupiter
            junit-jupiter
            5.8.2
        

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/793162.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存