java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用,从而保证了该变量的唯一性和准确性。
即有synchronized关键字修饰的语句块。
1 @SpringBootTest 2 //Ticket,实现Runnable接口 3 class Ticket implements Runnable{ 4 //定义变量tickets,并赋值10 5 private int tickets = 10; 6 //定义任意一个对象,用作同步代码块的锁 7 Object lock = new Object(); 8 9 //实现接口中的run()方法 10 @Override 11 public void run() { 12 while (true){ 13 synchronized (lock){ 14 try { 15 Thread.sleep(10); 16 }catch (InterruptedException e){ 17 e.printStackTrace(); 18 } 19 if (tickets > 0){ 20 System.out.println(Thread.currentThread().getName() + "---卖出的票" + tickets--); 21 }else { 22 //如果tickets 小于0 ,跳出循环 23 break; 24 } 25 } 26 } 27 } 28 } 29 public class Example { 30 public static void main(String[] args) { 31 //创建Ticket对象 32 Ticket ticket = new Ticket(); 33 //开启四个线程 34 new Thread(ticket,"线程一").start(); 35 new Thread(ticket,"线程二").start(); 36 new Thread(ticket,"线程三").start(); 37 new Thread(ticket,"线程四").start(); 38 } 39 }
运行结果:
将有关tickets变量的操作全部都放到同步代码块中,为了保证线程的持续执行,将同步代码块放在死循环中,直到tickets<0时跳出循环,持续在获得锁对象时有一定的随机性,在整个程序的运行期间,线程二和线程三始终未获得锁对象。
在方法面前同样可以使用synchronized关键字来修饰,被修饰的方法为同步方法,它能实现和同步代码块同样的功能。
具体语法格式:
1 @SpringBootTest 2 //Ticket,实现Runnable接口 3 class Ticket implements Runnable{ 4 //定义变量tickets,并赋值10 5 private int tickets = 10; 6 7 //实现接口中的run()方法 8 public void run() { 9 while (true){ 10 saleTicket(); //调用售票方法 11 if (tickets <=0){ 12 break; 13 } 14 } 15 16 } 17 //定义一个同步方法saleTicket 18 private synchronized void saleTicket(){ 19 if (tickets > 0){ 20 try { 21 Thread.sleep(100); 22 }catch (InterruptedException e){ 23 e.printStackTrace(); 24 } 25 System.out.println(Thread.currentThread().getName() + "卖出的票 --" + tickets --); 26 } 27 } 28 } 29 public class Example { 30 public static void main(String[] args) { 31 //创建Ticket对象 32 Ticket ticket = new Ticket(); 33 //开启四个线程 34 new Thread(ticket,"线程一").start(); 35 new Thread(ticket,"线程二").start(); 36 new Thread(ticket,"线程三").start(); 37 new Thread(ticket,"线程四").start(); 38 } 39 }
运行结果:
将售票代码抽取为售票方法saleTicket(),并用synchronized关键字把saleTicket()修饰为同步方法,实现了和同步代码块一样的效果。
原文:https://www.cnblogs.com/wx60079/p/13297948.html