• java中synchronized的使用


    synchronized是Java中的关键字,是一种同步锁。

    synchronized分对象锁和类的锁两种。

    (一)通常synchronized 方法和synchronized(this){}都是属于对象锁(或者实例锁)。
    每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。

    对象锁synchronized对于同一个实例有效。举例如下:
    
    public class C implements Runnable {
    	   private static int count;
    
    	   public C() {
    	      count = 0;
    	   }
    
    	   public  void run() {
    	      synchronized(this) {
    	         for (int i = 0; i < 5; i++) {
    	            try {
    	               System.out.println(Thread.currentThread().getName() + ":" + (count++));
    	               Thread.yield();
    	            } catch (Exception e) {
    	               e.printStackTrace();
    	            }
    	         }
    	      }
    	   }
    
    	   public int getCount() {
    	      return count;
    	   }
    	   public static void main(String[] args) {
    		   // C syncThread = new C();
    		   Thread thread1 = new Thread(new C(), "SyncThread1");   
    		   Thread thread2 = new Thread(new C(), "SyncThread2");
    		   thread1.start();
    		   thread2.start();
    	}
    }
    
    输出结果:
    SyncThread1:0
    SyncThread2:1
    SyncThread1:2
    SyncThread2:3
    SyncThread1:4
    SyncThread2:5
    SyncThread1:6
    SyncThread2:7
    SyncThread1:8
    SyncThread2:9
    
    两个线程是同时执行的,并没有synchronized的效果。因为两个线程执行的任务实例是不同的,都是重新new C()
    

    如果修改上面代码中的main函数部分,修改如下:

    public static void main(String[] args) {
    		   C syncThread = new C();
    		   Thread thread1 = new Thread(syncThread, "SyncThread1");// 
    		   Thread thread2 = new Thread(syncThread, "SyncThread2");
    		   thread1.start();
    		   thread2.start();
    	   }
    
    输出结果:
    SyncThread1:0
    SyncThread1:1
    SyncThread1:2
    SyncThread1:3
    SyncThread1:4
    SyncThread2:5
    SyncThread2:6
    SyncThread2:7
    SyncThread2:8
    SyncThread2:9
    
    这时synchronized起作用了,线程SyncThread1执行完毕释放锁后,SyncThread2才开始执行,因为线程任务的实例是同一个syncThread 
    

    那么问题来了,要是我想不同的任务实例也达到synchronized的效果应该怎么办?这时候就需要用到类的锁。

    (二)类锁:举例如下(还是刚才上面的例子):

    public class C implements Runnable {
    	   private static int count;
    
    	   public C() {
    	      count = 0;
    	   }
    
    	   public  void run() {
    	      synchronized(C.class) {  //把this改成C.class变成类的锁
    	         for (int i = 0; i < 5; i++) {
    	            try {
    	               System.out.println(Thread.currentThread().getName() + ":" + (count++));
    	               Thread.yield();
    	            } catch (Exception e) {
    	               e.printStackTrace();
    	            }
    	         }
    	      }
    	   }
    
    	   public int getCount() {
    	      return count;
    	   }
    	   public static void main(String[] args) {
    		   Thread thread1 = new Thread(new C(), "SyncThread1");
    		   Thread thread2 = new Thread(new C(), "SyncThread2");
    		   thread1.start();
    		   thread2.start();
    	   }
    }
    
    输出结果:
    SyncThread1:0
    SyncThread1:1
    SyncThread1:2
    SyncThread1:3
    SyncThread1:4
    SyncThread2:5
    SyncThread2:6
    SyncThread2:7
    SyncThread2:8
    SyncThread2:9
    
    这时候就达到了目的,用到的就是类的锁,即使不同的任务实例也可以实现同步功能。
    

    以上代码只作示例说明。

  • 相关阅读:
    jsgraphics插件图形库
    MySQL 基础知识
    第四天:任务开始——网络驱动
    第三天:软件著作权申请
    第二天:办公流程及软件安装
    第一天:products和一些感想
    IMX6Q RTC驱动分析
    PLATFORM设备驱动
    字符设备驱动以及杂项设备驱动
    C程序编译过程及优化选项介绍
  • 原文地址:https://www.cnblogs.com/hts-technology/p/7535578.html
Copyright © 2020-2023  润新知