在java语言中,我们常常会用到多线程相关的操作,但是多线程操作中可能会出现一些问题。
现在给定一个抢票的多线程代码
class MyThread implements Runnable{ int a = 10;//票数 @Override public void run() { while(true) { if(a>0) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"买票。剩余票数"+ --a); } else { System.out.println("票卖光了"); break; } } } } public class TheadOperation { public static void main(String[] args) throws InterruptedException { MyThread mt = new MyThread(); new Thread( mt,"a1").start(); new Thread(mt,"a2").start(); new Thread( mt,"a3").start(); } }
这个代码通过a1,a2,a3三个线程来执行抢票的工作,但是当票数为1的时候,三个线程同时可以进入售票过程,--a会被执行,所以最终的票数将变成-2,这就是一个严重的错误,所以就需要线程同步了。
首先,什么是线程同步?百度百科的回答是:即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态,实现线程同步的方法有很多,临界区对象就是其中一种。
通俗的来说就是多个操作在同一时间内,只能有一个线程进行,其他的线程要等此线程执行完了之后才可以继续执行。
通过关键字synchronized来实现线程同步。
可以有两种方法,一种是代码块形式,一种是关键字修饰方法的形式。
首先给出代码块形式:
1 class MyThread implements Runnable{ 2 int a = 1000000; 3 @Override 4 public void run() 5 { 6 while(true) 7 { 8 synchronized(this) 9 { 10 if(a>0) 11 { 12 try { 13 Thread.sleep(1); 14 } catch (InterruptedException e) { 15 e.printStackTrace(); 16 } 17 System.out.println(Thread.currentThread().getName()+"买票。剩余票数"+ --a); 18 } 19 else 20 { 21 System.out.println("票卖光了"); 22 break; 23 } 24 } 25 } 26 } 27 }
public class TheadOperation {
public static void main(String[]
args) throws InterruptedException {
MyThread mt = new MyThread();
new Thread(
mt,"a1").start();
new
Thread(mt,"a2").start();
new Thread(
mt,"a3").start();
}
}
synchronized(同步对象){代码操作}
通过该操作,就完成了将代码块中的内容线程同步。
然后是修饰方法:
class MyThread implements Runnable{ int a = 10000; public synchronized boolean abc() { if(a>0) { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"买票。剩余票数"+ --a); return true; } else { System.out.println("票卖光了"); return false; } } @Override public void run() { while(abc()) { } } } public class TheadOperation { public static void main(String[] args) throws InterruptedException { MyThread mt = new MyThread(); new Thread( mt,"a1").start(); new Thread(mt,"a2").start(); new Thread( mt,"a3").start(); } }
通过如此也可以实现方法体内线程同步。
由于线程同步导致同一时间内只有一个线程可进行操作,其带来的一个问题就是开销大,会影响程序的性能,所以要谨慎使用。
原文:https://www.cnblogs.com/wu199723/p/12219573.html