java线程中的同步
一、文章前言:
努力学习,放飞自我
二、什么是线程同步:
当使用多个线程来访问同一个数据时,非常容易出现线程安全问题(比如多个线程都在操作同一数据导致数据不一致),所以我们用同步机制来解决这些问题。同步就是让每个线程获得的资源是之前线程处理之后的,数据一致。
实现同步机制有两个方法:
1.同步代码块:
synchronized(同一个数据){} 同一个数据:就是N条线程同时访问一个数据。
2.同步方法:
public synchronized 数据返回类型 方法名(){}
就是使用 synchronized 来修饰某个方法,则该方法称为同步方法。对于同步方法而言,无需显示指定同步监视器,同步方法的同步监视器是 this 也就是该对象的本身(这里指的对象本身有点含糊,其实就是调用该同步方法的对象)通过使用同步方法,可非常方便的将某类变成线程安全的类。
本文将使用同步方法来给读者展示同步的效果
下面的先给读者展示一下单个线程处理资源的代码以及运行结果。
class MyThread implements Runnable{
private int ticket = 5 ; // 假设一共有5张票
public void run(){
for(int i=0;i<100;i++){
this.sale() ; // 调用同步方法
}
}
public void sale(){ // 声明同步方法
if(ticket>0){ // 还有票
try{
Thread.sleep(300) ; // 加入延迟
}catch(InterruptedException e){
e.printStackTrace() ;
}
System.out.println("卖票:ticket = " + ticket-- );
}
}
};
public class SyncDemo03{
public static void main(String args[]){
MyThread mt = new MyThread() ; // 定义线程对象
Thread t1 = new Thread(mt) ; // 定义Thread对象
t1.start() ;
}
};
运行结果:
这是预料之中的结果
接下来展示当多个线程同时进行处理这一个资源的时候结果是什么
class MyThread implements Runnable{
private int ticket = 5 ; // 假设一共有5张票
public void run(){
for(int i=0;i<100;i++){
this.sale() ; // 调用同步方法
}
}
public void sale(){ // 声明同步方法
if(ticket>0){ // 还有票
try{
Thread.sleep(300) ; // 加入延迟
}catch(InterruptedException e){
e.printStackTrace() ;
}
System.out.println("卖票:ticket = " + ticket-- );
}
}
};
public class SyncDemo03{
public static void main(String args[]){
MyThread mt = new MyThread() ; // 定义线程对象
Thread t1 = new Thread(mt) ; // 定义Thread对象
Thread t2 = new Thread(mt) ; // 定义Thread对象
Thread t3 = new Thread(mt) ; // 定义Thread对象
t1.start() ;
t2.start() ;
t3.start() ;
}
};
运行结果:
很明显我们看到结果和我们预期的有很大差别,这是为什么呢?如我们文章开头所说,当多个线程同时处理同一个资源的时候会出现数据不一致的情况(程序运行结果本应该是当票的数量为0时就不能够继续卖票了但是这里却出现错误这就是多个线程未同步带来的问题),这个时候该怎么办呢?看下面代码:
class MyThread implements Runnable{
private int ticket = 5 ; // 假设一共有5张票
public void run(){
for(int i=0;i<100;i++){
this.sale() ; // 调用同步方法
}
}
public synchronized void sale(){ // 声明同步方法
if(ticket>0){ // 还有票
try{
Thread.sleep(300) ; // 加入延迟
}catch(InterruptedException e){
e.printStackTrace() ;
}
System.out.println("卖票:ticket = " + ticket-- );
}
}
};
public class SyncDemo03{
public static void main(String args[]){
MyThread mt = new MyThread() ; // 定义线程对象
Thread t1 = new Thread(mt) ; // 定义Thread对象
Thread t2 = new Thread(mt) ; // 定义Thread对象
Thread t3 = new Thread(mt) ; // 定义Thread对象
t1.start() ;
t2.start() ;
t3.start() ;
}
};
运行结果:
这个代码中我们在sale()方法中加上了同步的关键字,说明我们定义的方法是线程同步的。看结果对比也能发现同步和不同步的区别到底是什么了。加了同步之后即使多个线程一起处理同一个资源的时候也不会出现数据不一致的情况。
(如果疑问请留言,如有错误请指正)