本篇是为了同步处理操作。
通过观察可以发现,以上程序所带来的最大问题在:判断和修改数据是分开执行的,即某几个线程可以同时进行这些功能。
然而我们要实现卖票功能,判断和修改数据应该要由单个线程执行完,别的线程才能进行之后的操作,因而要加锁。
在Java里面如果想要实现线程同步,可以使用synchronized关键字来加锁。而这个关键字可以通过两种方式使用。
1.同步代码块(同步块必须锁定一个对象,一般就是锁当前对象)
2.同步方法
范例:观察同步块
package TestDemo;
class MyThread implements Runnable{//Runnable接口子类,也是线程公有对象,其实例化对象在堆中
private int ticket=5;
@Override
public void run() {
for (int i = 0; i < 20; i++) {
synchronized(this){//当前操作每次只允许一个对象进入
if(this.ticket>0){
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+",sell ticket="+this.ticket--);
}
}
}
}
}
public class TestDemo{
public static void main(String[] args)throws Exception{
MyThread mt=new MyThread();
new Thread(mt,"seller A").start();
new Thread(mt,"seller B").start();
new Thread(mt,"seller C").start();
new Thread(mt,"seller D").start();
}
}
结果:
image.png
成功了。
范例:观察同步方法
package TestDemo;
class MyThread implements Runnable{//Runnable接口子类,也是线程公有对象,其实例化对象在堆中
private int ticket=5;
@Override
public void run() {
for (int i = 0; i < 20; i++) {
this.sale();//调用同步方法
}
}
public synchronized void sale(){//同步方法
if(this.ticket>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+",sell ticket="+this.ticket--);
}
}
}
public class TestDemo{
public static void main(String[] args)throws Exception{
MyThread mt=new MyThread();
new Thread(mt,"seller A").start();
new Thread(mt,"seller B").start();
new Thread(mt,"seller C").start();
new Thread(mt,"seller D").start();
}
}
结果:
image.png
也实现了。
中间件会帮我们实现一部分同步操作,没有的轮子可以自己写。同步操作与异步操作相比,异步操作的执行操作快,但是同步操作的线程安全性高。
网友评论