JAVA线程-----同步处理的三种方法

线程安全

1、多线程的执行顺序不可重现,但是必须要求执行结果必须可以重现。

2、线程的共享数据操作不完整性就一定会出现数据被破坏,而导致结果无法预知的问题—线程的安全问题。

同步处理的引入

1、在java语言中存在两种内建的synchronized语法:synchronized代码块和synchronized方法( 静态方法和非静态方法)可以解决线程安全问题。

2、首先synchronized将并行改为串行,当然会影响程序的执行效率,执行速度会受到影响。其次synchronized操作线程的堵塞,也就是由操作系统控制CPU的内核进行上下文的切换,这个切换本身也是耗时的。所以使用synchronized关键字会降低程序的运行效率。

问题:

线程安全是并发编程中的重要关注点,应该注意到的是,造成线程安全问题的主要诱因有两点,一是存在共享数据(也称临界资源),二是存在多条线程共同操作共享数据

解决方案:

当存在多个线程操作共享数据时,需要保证同一时刻有且只有一个线程在操作共享数据,其他线程必须等到该线程处理完数据后再进行,这种方式有个名称叫互斥锁,即能达到互斥访问目的的锁,也就是说当一个共享数据被当前正在访问的线程加上互斥锁后,在同一个时刻,其他线程只能处于等待的状态,直到当前线程处理完毕释放该锁

  • 在Java中每个对象都有一个对象锁,其实就是对象头上的一个标记值而已
  • 同步处理的目标实际上就是实现线程排队执行的目的

一、同步方法

针对临界资源的修改方法上添加同步约束—synchronized
临界资源—被多个线程所共享操作的对象

public class OperNum {
    
    
	private int target;  //操作的数据
	//操作数据的方法
	public synchronized void add() {
    
     //synchronized方法的同步锁为当前对象
		target++;
		System.out.println(Thread.currentThread().getName()+"add..."+target);
	}
	
	public synchronized void sub() {
    
    
		target--;
		System.out.println(Thread.currentThread().getName()+"sun..."+target);
	}
}

上面代码的原理:
当一个线程在执行add方法时,其它线程不能执行add或者sub方法【同步方法都不能执行,因为是synchronized关键字会引入一个互斥锁,只有拥有锁的线程才能执行同步方法,其它线程只能阻塞等待】,synchronized属于重入锁,即当前线程可以执行其它的synchronized方法,但是其它线程不能执行当前对象中的synchronized方法,可以执行没有synchronized约束的方法


二、同步代码块

这里的锁实际上是人为进行指定,推荐使用。

synchronized(){
    
     执行的代码块}


public class MyThread extends Thread {
    
    
	private static int target = 0;  //操作目标   临界资源
	private boolean flag = true;  //不是临界资源    用来判断进行加操作 还是减 操作。
	
	private static Object lock = new Object();   //人为定义一个锁;
	public MyThread(boolean flag) {
    
    
		this.flag = flag;
	}
	
	public void run() {
    
    
	for(int i = 0;i<20;i++) {
    
    
		synchronized (lock) {
    
           //synchronized (lock) 可以保证{}中的代码执行具备原子性
			if(flag)
				target++;
			else
				target--;
			System.out.println(Thread.currentThread().getName()+(flag ? "add" : "sub")+"----"+target);
		}
	}
	}
	public static void main(String[] args) {
    
    
		for(int i = 0;i<4;i++) {
    
    
			new MyThread(i%2==0).start();
		}
	}
}

三、同步静态方法

当前类对象充当锁,所有静态方法互斥

  • 和非静态方法不互斥,因为非静态同步方法的锁是当前对象,不是类锁
public class OperNum {
    
    
	private static int target = 10;  //操作的数据
	 //针对操作数据的方法
	
	public synchronized  static void add() {
    
    
		target++;
		System.out.println(Thread.currentThread().getName()+"add---"+target);
	}
	
	public synchronized  static void sub() {
    
    
		target--;
		System.out.println(Thread.currentThread().getName()+"sub--"+target);
	}
}


剩下的 有时间再补

猜你喜欢

转载自blog.csdn.net/weixin_42437438/article/details/113871662