线程安全问题的判断
1是否是多线程环境
2是否有共享数据
3是否有多条语句操作共享数据
解决方法:在共享数据那里添加锁,如下
synchronized(对象){
需要同步的代码;
}
线程共享数据出问题的例子:
共同使用的多线程:
package cn;
public class MyThread implements Runnable {
private static int max = 100;
@Override
public void run() {
while (true) {
if (max > 0) {
// 3个线程同时进来,都停在这里max=1
try {
Thread.sleep(100); //3个线程同时进来,都停在这里,线程1执行完,这时max=0
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + max--);
}
}
}
}
线程没有同步出现的问题:
public static void main(String[] args) {
MyThread st = new MyThread();
// 创建三个线程对象
Thread t1 = new Thread(st, "线程1");
Thread t2 = new Thread(st, "线程2");
Thread t3 = new Thread(st, "线程3");
t1.start();
t2.start();
t3.start();
}
出问题的输出:
线程1:6
线程3:5
线程2:4
线程1:3
线程3:2
线程2:1
线程1:0
线程3:-1
解决方法:
1自定义锁,同步在方法上
public class MyThread implements Runnable {
private static int max = 100;
//创建任意锁对象
private Object obj = new Object();
@Override
public void run() {
while (true) {
////线程同时进来,都停在这里,等其他线程结束完才申请进去的资格
synchronized (obj){//
if (max > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + max--);
}
}
}
}
//同步在方法上
private synchronized void sub(){
if (max > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + max--);
}
}
}
2.锁对象Lock
package cn;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* * Lock:
* void lock(): 获取锁。
* void unlock():释放锁。
* ReentrantLock是Lock的实现类.
* @author Administrator
*
*/
public class MyThread implements Runnable {
private static int max = 100;
//创建任意锁对象
private Object obj = new Object();
// 定义锁对象
private Lock lock=new ReentrantLock();//ReentrantLock是Lock的实现类.
@Override
public void run() {
//lock的实现
while (true) {
////线程同时进来,都停在这里,等其他线程结束完才申请进去的资格
lock.lock();
if (max > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + max--);
}
lock.unlock();
}
}
}