同步问题的引出
在多线程的处理之中,可以利用Runnable描述多个线程操作的资源,而Thread描述每一个线程对象,于是当多个线程访问同一资源的时候如果处理不当就会产生数据的错误操作
下面编写一个简单的买票程序,将创建若干个线程对象实现卖票的处理操作.
public class MyThread6 implements Runnable{
private int ticket = 10;
public void run(){
while(true) {
if (this.ticket > 0) {
try {
Thread.sleep(1000); // 模拟网络延迟
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName() + "卖票\t ticket =" + this.ticket--);
} else {
System.out.println("*******票已经卖光了*****");
break;
}
}
}
}
MyThread6 myt = new MyThread6();
new Thread(myt,"售票厅1").start();
new Thread(myt,"售票厅2").start();
new Thread(myt,"售票厅3").start();
结果:
这个问题就叫线程问题的不同步。
同步处理的解决方法
经过分析之后已经可以确定同步问题所产生的主要原因了,那么下面就需要进行同步问题的解决,但是解决同步问题的关键是锁,指的是当某一个线程执行操作的时候,其他线程外面等待。
如果要想在程序之中实现这把锁的功能,就可以使用synchronized关键字来实现,利用此关键字可以定义同步方法或者同步代码块,在同步代码块的操作里面的代码只允许一个线程执行
- 利用同步代码块进行处理
synchronized(同步对象){
同步代码操作
}
一般要进行同步对象处理的时候可以采用当前对象this进行同步。
public class MyThread7 implements Runnable{
private int ticket = 10;
@Override
public void run(){
while (true){
synchronized (this){
if (this.ticket>0){
System.out.println(Thread.currentThread().getName()+"卖票\t ticket="+this.ticket--);
}else {
System.out.println("-------票已经卖完了---------");
break;
}
}
}
}
}
MyThread7 myt = new MyThread7();
new Thread(myt,"售票厅1").start();
new Thread(myt,"售票厅2").start();
new Thread(myt,"售票厅3").start();
加入同步处理之后,程序的整体的性能下降了。同步实际上会造成性能降低。
2. 在方法定义上使用synchronized关键字即可。
public class MyThread8 implements Runnable{
private int ticket = 10;
public synchronized boolean sale(){
if (this.ticket>0){
System.out.println(Thread.currentThread().getName()+"卖票\t ticket="+ticket--);
return true;
}else {
System.out.println("票已经买完了");
return false;
}
}
@Override
public void run(){
while (this.sale()){
};
}
}
MyThread8 myt = new MyThread8();
new Thread(myt,"售票厅1").start();
new Thread(myt,"售票厅2").start();
new Thread(myt,"售票厅3").start();
在日后学习Java类库的时候会发现,系统中许多的类上使用的同步处理采用的都是同步方法
同步会造成性能下降
死锁
死锁是在进行多线程同步的处理之中有可能产生的一种问题,所谓的死锁指的是若干个线程彼此互相等待的状态。下面通过一个简单的代码来观察一下死锁的表现形式,但是对于此代码不作为重点。
public class MyThread9 implements Runnable {
private Jian jj = new Jian();
private XiaoQiang xq= new XiaoQiang();
@Override
public void run(){
jj.say(xq);
}
public void DeadLock(){
new Thread(this).start();
xq.say(jj);
}
public static void main(String args[]){
new MyThread9();
}
}
class Jian{
public synchronized void say(XiaoQiang xq){
System.out.println("阿健说,此路是我开,要想从此过,留下10块钱");
}
public synchronized void get(){
System.out.println("阿健说,得到了10块钱,可以买饭吃了,于是让出了路。");
}
}
class XiaoQiang{
public synchronized void say(Jian jj){
System.out.println("小强说,让我先跑,我再给你钱");
}
public synchronized void get(Jian jj){
System.out.println("小强说,逃过了一劫,可以继续送快餐了");
}
}
现在死锁造成的主要原因是因为彼此都在互相等待着,等待着对方让出资源。死锁实际上是一种开发中出现的不确定的状态,有的时候代码如果处理不当则会不定期的处理死锁,这是属于正常开发中的调试问题。