java多线程安全问题

值得注意的一点是,QObject及其所有子类都不是线程安全的(但都是可重入的)。因此,你不能有两个线程同时访问一个QObject对象,除非这个对象的内部数据都已经很好地序列化(例如为每个数据访问加锁)。


如果判断一个类是否线程安全的,

看多个线程同时访问该类中的一个成员变量,是否需要加锁,


可以说,没有线程安全的类,即多线程访问的时候,几乎都需要加锁

下面看例子,

package com.niuli.develop;

public class Test {
    public static void main (String [] args) {
        Cus c = new Cus();
        new Thread(c).start();
        new Thread(c).start();
    }
}

class Bank{
    private int sum = 0;
    public void add(int n) {
        sum = sum + n;
        System.out.println("sum= "+sum);
    }
}

class Cus implements Runnable{
    Bank b = new Bank();
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            b.add(100);
        }
    }
}

很简单的例子, 
首先第一步,找到多线程运行的代码

也就是run方法里面的代码
for (int i = 0; i < 3; i++) {
            b.add(100);
        }
        另外这里用到了Add方法,所以add也算
 public void add(int n) {
        sum = sum + n;
        System.out.println("sum= "+sum);
    }

第二步,找到共享数据

Bank b = new Bank();
private int sum = 0;

第三步,明确多线程使用的共享数据. 
首先对于数据b就一条语句使用了这个共享变量,因此不会出现线程不安全,但是对于sum,有两条语句使用的,所以就会出现线程安全问题,

解决办法,同步块

Object obj = new Object();
    public void add(int n) {
        synchronized (obj) {
            sum = sum + n;
            System.out.println("sum= "+sum);
        }
    }

或者,给方法加锁

public synchronized void add(int n) {
            sum = sum + n;
            System.out.println("sum= "+sum);
    }

以上就是线程安全的解决办法,同步机制虽然游侠,但是带来了一定的性能损耗,所以,对操作共享数据的部分执行同步,尽量减少这种损耗


线程安全类

在集合框架中,有些类是线程安全的,这些都是jdk1.1中的出现的。在jdk1.2之后,就出现许许多多非线程安全的类。 下面是这些线程安全的同步的类:

vector:就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。

statck:堆栈类,先进后出

hashtable:就比hashmap多了个线程安全

enumeration:枚举,相当于迭代器

除了这些之外,其他的都是非线程安全的类和接口。

线程安全的类其方法是同步的,每次只能一个访问。是重量级对象,效率较低。



猜你喜欢

转载自blog.csdn.net/cdaimadada/article/details/79999872