线程同步的案例:
对于火车票,不同售票点,卖的票是一样的,这就涉及到资源共享,保证一张票只能卖给一个人,多个售票点好比多个线程
线程同步的概念:
1.多线程共享数据时,会发生线程不安全的情况
2.多线程共享数据必须使用同步
线程进行同步,有以下三种方法:
1.synchronized(要同步的对象){
要同步的操作;
}
示例代码:
public class ThreadDemo2 {
public static void main(String[] args) {
MyRunnable3 mr3 = new MyRunnable3();
Thread t1 = new Thread(mr3);
Thread t2 = new Thread(mr3);
t1.start();
t2.start();
}
}
class MyRunnable3 implements Runnable{
private int ticket = 10;
Object obj = new Object();
@Override
public void run() {
for (int i = 0; i < 50; i++) {
if(ticket>0){
synchronized (obj){
ticket--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("购票成功,剩余票数:"+ticket);
}
}
}
}
}
运行效果:为什么到-1才结束???因为没有把判断放进同步线程中!!!
2.同步方法
public synchronized void method(){
要同步的操作;
}
public class ThreadDemo2 {
public static void main(String[] args) {
MyRunnable3 mr3 = new MyRunnable3();
Thread t1 = new Thread(mr3);
Thread t2 = new Thread(mr3);
t1.start();
t2.start();
}
}
class MyRunnable3 implements Runnable{
private int ticket = 10;
Object obj = new Object();
@Override
public void run() {
for (int i = 0; i < 50; i++) {
method();
}
}
//同步方法:同步的对象是当前对象(this)
private synchronized void method(){
if(ticket>0){
ticket--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("购票成功,剩余票数:"+ticket);
}
}
}
运行效果:3.Lock(ReentrantLock)
此方法更加灵活
示例代码:
import java.util.concurrent.locks.ReentrantLock;
public class ThreadDemo2 {
public static void main(String[] args) {
MyRunnable3 mr3 = new MyRunnable3();
Thread t1 = new Thread(mr3);
Thread t2 = new Thread(mr3);
t1.start();
t2.start();
}
}
class MyRunnable3 implements Runnable{
private int ticket = 10;
Object obj = new Object();
@Override
public void run() {
for (int i = 0; i < 50; i++) {
method();
}
}
//互斥锁
ReentrantLock lock = new ReentrantLock();
//同步方法:同步的对象是当前对象(this)
private void method(){
lock.lock(); //锁
try {
if (ticket > 0) {
ticket--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("购票成功,剩余票数:" + ticket);
}
}finally { //finally确保一定会释放锁,避免死锁
lock.unlock(); //释放锁
}
}
}
运行效果:同步准则
1.多线程共享数据会有安全问题,使用同步可以解决安全问题,但同时会牺牲性能,所以同步的代码块要尽量保持简短,把不随数据变化的相关代码移出同步代码块
2.不要阻塞
3.在持有锁的时候,不要对其他对象调用方法