线程安全
如果有多个线程在同时运行,而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样 的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
解决线程安全(线程同步)
方法:
- 同步代码块
- 同步方法
- Lock锁
同步代码块
要解决上述多线程并发访问一个资源的安全性问题:Java中提供了同步机制 (synchronized)来解决。
synchronized(同步锁){
需要同步操作的代码
}
同步锁:
对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁.
- 锁对象 可以是任意类型。
- 多个线程对象 要使用同一把锁。
E:
package 线程安全.dome01Synchronized;
public class dome01 implements Runnable {
private int ticke=100;
private Object obj = new Object();
@Override
public void run() {
while (true){
tict();
}
}
private synchronized void tict(){
if(ticke>0){
try{
Thread.sleep(100); }
catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在卖第"+ticke+"张票!!");
ticke--;}
}
}
同步方法
同步方法:
- 使用synchronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外 等着
格式:
public synchronized void method(){
可能会产生线程安全问题的代码
}
同步锁是谁:
- 对于非static方法,同步锁就是this。
- 对于static方法,我们使用当前方法所在类的字节码对象(类名.class)。 对于static方法,我们使用当前方法所在类的字节码对象(类名.class)。
E:
package 线程安全.同步方法;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class dome01 implements Runnable {
private int ticke=100;
private Object obj = new Object();
Lock lock = new ReentrantLock();
@Override
public void run() {
while (true){
lock.lock();
if(ticke>0){
try{
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"正在卖第"+ticke+"张票!!");
ticke--;}
catch(InterruptedException e){
e.printStackTrace();
lock.unlock();
}
}
}
}
}
Lock锁
java.util.concurrent.locks.Lock 机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作, 同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。
Lock锁也称同步锁,加锁与释放锁方法化了,如下:
public void lock() :加同步锁。
public void unlock() :释放同步锁。
E:
package 线程安全.Lock锁;
public class dome01 implements Runnable {
private int ticke=100;
private Object obj = new Object();
@Override
public void run() {
while (true){
synchronized (obj){
if(ticke>0){
try{
Thread.sleep(100); }
catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在卖第"+ticke+"张票!!");
ticke--;
}
}
}
}
}
main方法
package 线程安全.Lock锁;
public class dome0 {
public static void main(String[] args) {
dome01 t1 = new dome01();
Thread m1 = new Thread(t1);
Thread m2 = new Thread(t1);
Thread m3 = new Thread(t1);
m1.start();
m2.start();
m3.start();
}
}