在进行线程代码的实现时会存在部分安全问题
比如下列的售票例子
public class DemoMyThread {
public static void main(String[] args) {
Runnable run = new Runnableimpl(); // 多态
//开放三个线程
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
}
}
class Runnableimpl implements Runnable {
private int ticket = 100;
@Override
public void run() {
while (true) {
if (ticket > 0) {
try {
Thread.sleep(10);
System.out.println(Thread.currentThread().getName() + "正在售出第" + ticket + "张票");
ticket--;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
代码的输出就出现了重复售票和售出不存在的票等安全问题
要解决线程安全问题有三种方法:
1.同步代码块
在实现了共享数据的代码前创建一个同步代码块的锁对象
锁对象的作用:
把同步代码块锁住,只让一个线程在同步代码块中执行。
public class DemoMyThread {
public static void main(String[] args) {
Runnable run = new Runnableimpl(); // 多态
//开放三个线程
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
}
}
class Runnableimpl implements Runnable {
private int ticket = 100;
//创建一个锁对象
Object obj = new Object();
@Override
public void run() {
while (true) {
//同步代码块
synchronized (obj) {
if (ticket > 0) {
try {
Thread.sleep(10);
System.out.println(Thread.currentThread().getName() + "正在售出第" + ticket + "张票");
ticket--;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
2.同步方法
把访问了共享数据的代码抽取出来放在一个方法中
package Thread;
public class Demo04 {
public static void main(String[] args) {
Runnable run = new Runnableimpl(); // 多态
// 开放三个线程
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
}
}
class Runnableimpl implements Runnable {
private int ticket = 100;
@Override
public void run() {
while (true) {
soldTicket();
}
}
public synchronized void soldTicket() {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在售出第" + ticket + "张票");
ticket--;
}
}
}
3.Lock锁
在成员位置创建一个ReentrantLock对象,再调用接口中的lock方法和unlock方法对代码进行锁的获取和释放
package Thread;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo04 {
public static void main(String[] args) {
Runnable run = new Runnableimpl(); // 多态
// 开放三个线程
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
}
}
class Runnableimpl implements Runnable {
private int ticket = 100;
//在成员位置创建一个ReentrantLock对象
Lock l = new ReentrantLock();
@Override
public void run() {
while (true) {
//获取锁
l.lock();
if (ticket > 0) {
try {
Thread.sleep(10);
System.out.println(Thread.currentThread().getName() + "正在售出第" + ticket + "张票");
ticket--;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//释放锁
l.unlock();
}
}
}
}
}