认识java中线程安全问题

原创 2017年03月16日 16:32:33

出现场景: 多个线程同时操作一个对象,如果该对象没有线程安全的控制,便会出现线程安全问题。例如:我们有一个类A

public class A{
    int count=0;
    public void add1000(){
        for(int i=0;i<1000;i++){
            count++;
            System.out.println(count);
        }

    }
}

如上代码所示,A中有一个成员变量count,有一个让count加1000的方法,并打印。如果声明A一个对象,一个线程访问没问题,会从打印0~999。但当多个线程操作A的同一个对象,就可能发生一个现象:

public static void main(String[] args) {

        Run run = new Run();
        new Thread(new Runnable() {

            @Override
            public void run() {
                run.add1000("A");
            }

        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                run.add1000("B");
            }

        }).start();

    }

从上面的代码可以看到,启动了两个线程,每个线程都只是想让A的count打印从0到999,但由于线程之间的运行方式是轮着运行的(对线程运行方法不了解,可自行搜索学习),会导致这两个线程都操作count,count的值也是在一直变的,就不能保证add1000这个方法的原子性。

解决办法: 对于解决办法,java特别提供了保证线程安全的类和关键字,同时java的类中也有好多是线程安全和不安全两个版本。
首先最简单的解决办法就是使用synchronized关键字

public synchronized void add1000(String s) {
            for (int i = 0; i < 1000; i++) {
                count++;
                System.out.println(s + count);
            }

        }

在add1000方法前添加synchronized关键字便可保证该方法变成线程安全的,原理大概是,当某个线程调用此方法时,会获取该实例的对象锁,方法未结束之前,其他线程只能去等待。当这个方法执行完时,才会释放对象锁。其他线程才有机会去抢占这把锁,去执行该方法。同时该关键字也能同步代码块。

使用Lock类;lock是java concurrent包下的一个类,该类可以很自由的给任意代码段添加锁及释放锁。

public static void main(String[] args) {


        Lock lock = new ReentrantLock();
        Run run = new Run(lock);
        new Thread(new Runnable() {

            @Override
            public void run() {
                run.add1000("A");
            }

        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                run.add1000("B");
            }

        }).start();

    }

    public static  class Run {
        int count = 0;
        Lock lock;
        public Run(Lock lock){
            this.lock=lock;
        }

        // count加1000
        public synchronized void add1000(String s) {
            for (int i = 0; i < 1000; i++) {
                try{
                    lock.lock();
                    count++;
                    System.out.println(s + count);
                }finally{
                    lock.unlock();
                }

            }

        }

    }

如上代码便是使用Lock进行加锁,如果你把finally的释放锁代码注释掉,第二个线程就无法执行该,程序一直卡在这,因为线程一一直持有该段代码的锁,线程二一直等待获取锁,便发生了死锁堵塞。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Java中线程的创建使用及其安全问题

1.进程与线程   几乎所有的操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每个运行中的程序就是一个...

Java中线程安全问题个人理解

线程安全问题是一个比较高深的问题,是很多程序员比较难掌握的一个技术难点,如果一个程序员对线程掌握的很好的话,那么这个程序员的内功修炼的是相当的好。 在这里我主要说一下我对java中如何保证线程安全的...
  • com360
  • com360
  • 2011年09月18日 12:33
  • 1569

Java多线程中线程安全与锁问题

线程安全 无状态的对象一定是线程安全的。 要保持状态的一致性,就需要在单个原子操作中更新所有相关的状态变量。 并发环境中的原子性与事务应用程序中的原子性有着相同的含义—一组语句作为一个不可分割的单元...

关于Java OutputStream 线程安全问题

今天偶尔发现java的输出流的线程安全问题 先看代码吧 import java.io.File; import java.io.FileInputStream; import java.io.Fi...

浅谈利用同步机制解决Java中的线程安全问题

这篇博客是我的第一篇博客,介绍了利用同步机制解决Java中的线程安全问题。...

java解决线程不安全问题的方法

线程不安全问题 当多线程并发访问同一个资源时,容易出现不安全问题                                                      有时候我们分析打印结果,发...

Java线程安全问题,方法及内存模型

最近想将java基础的一些东西都整理整理,写下来,这是对知识的总结,也是一种乐趣。已经拟好了提纲,大概分为这几个主题: java线程安全,java垃圾收集,java并发包详细介绍,java profi...

java多线程安全问题

在上一篇博客中,初步解决了卖票
  • AS_MSDN
  • AS_MSDN
  • 2014年06月14日 14:07
  • 352

java中多线程安全问题产生&解决方案——同步方法

使用同步方法解决  格式:   修饰符 synchronized 返回值 方法名(){   } package com.itheima_05; /* * 同步方法:使用关键...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:认识java中线程安全问题
举报原因:
原因补充:

(最多只允许输入30个字)