文章目录
非线程安全会在多个线程对同一个实例变量进行并发访问时发生,产生的结果是脏读,也就是取到的数据是被更改过的。
synchronized同步方法
非线程安全问题
下面展示demo,存在非线程安全问题:
public class HasSelfNum {
int num = 0;
synchronized
public void add(String username) {
// int num = 0; 局部变量不存在非线程安全问题
try {
System.out.println("线程:" + Thread.currentThread().getName() + " 进入..");
if ("a".equals(username)) {
num = 100;
Thread.sleep(3000); // 挂起线程,把执行权交给别的线程。
} else {
num = 200;
}
System.out.println("username:" + username + ", num:" + num);
System.out.println("线程:" + Thread.currentThread().getName() + " 结束~");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ThreadA extends Thread {
private HasSelfNum h;
public ThreadA(HasSelfNum h) {
this.h = h;
}
public void run() {
h.add("a");
}
}
class ThreadB extends Thread {
private HasSelfNum h;
public ThreadB(HasSelfNum h) {
this.h = h;
}
public void run() {
h.add("b");
}
}
class Main {
public static void main(String[] args) {
HasSelfNum h = new HasSelfNum();
ThreadA a = new ThreadA(h);
ThreadB b = new ThreadB(h);
a.setName("a");
b.setName("b");
a.start();
b.start();
}
}
打印结果:
线程:a 进入..
线程:b 进入..
username:b, num:200
线程:b 结束~
username:a, num:200 //这里num应该输出100才正确
线程:a 结束~
非线程安全问题存在于实例变量中,解决这个问题只需要把执行方法同步,即加上synchronized:
synchronized
public void add(String username) {
}
打印结果:
线程:a 进入..
username:a, num:100
线程:a 结束~
线程:b 进入..
username:b, num:200
线程:b 结束~
如果是方法内部的私有变量则不存在非线程安全问题,这是因为方法内部对每个线程而言是独立的。
synchronized方法与锁对象
调用synchronized方法是同步的,那再调用非synchronized方法是怎么样的呢?
public class MyObject {
synchronized
public void methodA() {
try {
System.out.println("线程:" + Thread.currentThread().getName() + " 进入..");
Thread.sleep(2000);
System.out.println("线程:" + Thread.currentThread().getName() + " 结束~");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void methodB() {
try {
System.out.