多线程-synchronized关键字

Java多线程的同步:synchronized关键字、Lock接口、volatile关键字 Java 多线程同步是解决资源共享冲突的核心机制,主要通过协调线程对共享资源的访问顺序与权限,避免数据不一致和竞态条件。在多线程的环境中,经常会碰到数据的共享问题,即当多线程需要访问同一个资源时,它们需要以某种顺序来确保该资源在某一时刻只能被一个线程使用,否则,程序的运行结果将会是不可预料的,在这种情况下就必须对数据进行同步。例如多个线程同时对同一数据进行写操作。 阅读详情

1. synchronized原理

在java中,每一个对象有且仅有一个同步锁。这也意味着,同步锁是依赖于对象而存在。
当我们调用某对象的synchronized方法时,就获取了该对象的同步锁。例如,synchronized(obj)就获取了“obj这个对象”的同步锁。
不同线程对同步锁的访问是互斥的。也就是说,某时间点,对象的同步锁只能被一个线程获取到!通过同步锁,我们就能在多线程中,实现对“对象/方法”的互斥访问。 例如,现在有两个线程A和线程B,它们都会访问“对象obj的同步锁”。假设,在某一时刻,线程A获取到“obj的同步锁”并在执行一些操作;而此时,线程B也企图获取“obj的同步锁” —— 线程B会获取失败,它必须等待,直到线程A释放了“该对象的同步锁”之后线程B才能获取到“obj的同步锁”从而才可以运行。

 

2. synchronized基本规则

我们将synchronized的基本规则总结为下面3条,并通过实例对它们进行说明。
第一条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的该“synchronized方法”或者“synchronized代码块”的访问将被阻塞。
第二条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程仍然可以访问“该对象”的非同步代码块。
第三条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的其他的“synchronized方法”或者“synchronized代码块”的访问将被阻塞。

 

第一条

当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的该“synchronized方法”或者“synchronized代码块”的访问将被阻塞。
下面是“synchronized代码块”对应的演示程序。

  class MyRunable implements Runnable {
      
      @Override
      public void run() {
          synchronized(this) {
              try {  
                  for (int i = 0; i < 5; i++) {
                      Thread.sleep(100); // 休眠100ms
                      System.out.println(Thread.currentThread().getName() + " loop " + i);  
                 }
             } catch (InterruptedException ie) {  
             }
         }  
     }
 }
 
 public class Demo1_1 {
 
     public static void main(String[] args) {  
         Runnable demo = new MyRunable();     // 新建“Runnable对象”
 
         Thread t1 = new Thread(demo, "t1");  // 新建“线程t1”, t1是基于demo这个Runnable对象
         Thread t2 = new Thread(demo, "t2");  // 新建“线程t2”, t2是基于demo这个Runnable对象
         t1.start();                          // 启动“线程t1”
         t2.start();                          // 启动“线程t2” 
     } 
 }
 

运行结果:

t1 loop 0
t1 loop 1
t1 loop 2
t1 loop 3
t1 loop 4
t2 loop 0
t2 loop 1
t2 loop 2
t2 loop 3
t2 loop 4
 

结果说明:
run()方法中存在“synchronized(this)代码块”,而且t1和t2都是基于"demo这个Runnable对象"创建的线程。这就意味着,我们可以将synchronized(this)中的this看作是“demo这个Runnable对象”;因此,线程t1和t2共享“demo对象的同步锁”。所以,当一个线程运行的时候,另外一个线程必须等待“运行线程”释放“demo的同步锁”之后才能运行。

如果你确认,你搞清楚这个问题了。那我们将上面的代码进行修改,然后再运行看看结果怎么样,看看你是否会迷糊。修改后的源码如下:

  class MyThread extends Thread {
      
      public MyThread(String name) {
          super(name);
      }
  
      @Override
      public void run() {
          synchronized(this) {
             try {  
                 for (int i = 0; i < 5; i++) {
                     Thread.sleep(100); // 休眠100ms
                     System.out.println(Thread.currentThread().getName() + " loop " + i);  
                 }
             } catch (InterruptedException ie) {  
             }
         }  
     }
 }
 
 public class Demo1_2 {
 
     public static void main(String[] args) {  
         Thread t1 = new MyThread("t1");  // 新建“线程t1”
         Thread t2 = new MyThread("t2");  // 新建“线程t2”
         t1.start();                          // 启动“线程t1”
         t2.start();                          // 启动“线程t2” 
     } 
 }
 

代码说明:
比较Demo1_2 和 Demo1_1,我们发现,Demo1_2中的MyThread类是直接继承于Thread,而且t1和t2都是MyThread子线程。
幸运的是,在“Demo1_2的run()方法”也调用了synchronized(this),正如“Demo1_1的run()方法”也调用了synchronized(this)一样!
那么,Demo1_2的执行流程是不是和Demo1_1一样呢?
运行结果:

t1 loop 0
t2 loop 0
t1 loop 1
t2 loop 1
t1 loop 2
t2 loop 2
t1 loop 3
t2 loop 3
t1 loop 4
t2 loop 4
 

结果说明:
如果这个结果一点也不令你感到惊讶,那么我相信你对synchronized和this的认识已经比较深刻了。否则的话,请继续阅读这里的分析。
synchronized(this)中的this是指“当前的类对象”,即synchronized(this)所在的类对应的当前对象。它的作用是获取“当前对象的同步锁”。
对于Demo1_2中,synchronized(this)中的this代表的是MyThread对象,而t1和t2是两个不同的MyThread对象,因此t1和t2在执行synchronized(this)时,获取的是不同对象的同步锁。对于Demo1_1对而言,synchronized(this)中的this代表的是MyRunable对象;t1和t2共同一个MyRunable对象,因此,一个线程获取了对象的同步锁,会造成另外一个线程等待。

 

第二条

当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程仍然可以访问“该对象”的非同步代码块。
下面是“synchronized代码块”对应的演示程序。

  class Count {
  
      // 含有synchronized同步块的方法
      public void synMethod() {
          synchronized(this) {
              try {  
                  for (int i = 0; i < 5; i++) {
                      Thread.sleep(100); // 休眠100ms
                      System.out.println(Thread.currentThread().getName() + " synMethod loop " + i);  
                 }
             } catch (InterruptedException ie) {  
             }
         }  
     }
 
     // 非同步的方法
     public void nonSynMethod() {
         try {  
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(100);
                 System.out.println(Thread.currentThread().getName() + " nonSynMethod loop " + i);  
             }
         } catch (InterruptedException ie) {  
         }
     }
 }
 
 public class Demo2 {
 
     public static void main(String[] args) {  
         final Count count = new Count();
         // 新建t1, t1会调用“count对象”的synMethod()方法
         Thread t1 = new Thread(
                 new Runnable() {
                     @Override
                     public void run() {
                         count.synMethod();
                     }
                 }, "t1");
 
         // 新建t2, t2会调用“count对象”的nonSynMethod()方法
         Thread t2 = new Thread(
                 new Runnable() {
                     @Override
                     public void run() {
                         count.nonSynMethod();
                     }
                 }, "t2");  
 
 
         t1.start();  // 启动t1
         t2.start();  // 启动t2
     } 
 }
 

运行结果:

t1 synMethod loop 0
t2 nonSynMethod loop 0
t1 synMethod loop 1
t2 nonSynMethod loop 1
t1 synMethod loop 2
t2 nonSynMethod loop 2
t1 synMethod loop 3
t2 nonSynMethod loop 3
t1 synMethod loop 4
t2 nonSynMethod loop 4
 

结果说明:
主线程中新建了两个子线程t1和t2。t1会调用count对象的synMethod()方法,该方法内含有同步块;而t2则会调用count对象的nonSynMethod()方法,该方法不是同步方法。t1运行时,虽然调用synchronized(this)获取“count的同步锁”;但是并没有造成t2的阻塞,因为t2没有用到“count”同步锁。

 

第三条

当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的其他的“synchronized方法”或者“synchronized代码块”的访问将被阻塞。
我们将上面的例子中的nonSynMethod()方法体的也用synchronized(this)修饰。修改后的源码如下:

 class Count {
      // 含有synchronized同步块的方法
      public void synMethod() {
          synchronized(this) {
              try {  
                  for (int i = 0; i < 5; i++) {
                      Thread.sleep(100); // 休眠100ms
                      System.out.println(Thread.currentThread().getName() + " synMethod loop " + i);  
                 }
             } catch (InterruptedException ie) {  
             }
         }  
     }
 
     // 也包含synchronized同步块的方法
     public void nonSynMethod() {
         synchronized(this) {
             try {  
                 for (int i = 0; i < 5; i++) {
                     Thread.sleep(100);
                     System.out.println(Thread.currentThread().getName() + " nonSynMethod loop " + i);  
                 }
             } catch (InterruptedException ie) {  
             }
         }
     }
 }
 
public class Demo3 {
 
     public static void main(String[] args) {  
         final Count count = new Count();
         // 新建t1, t1会调用“count对象”的synMethod()方法
         Thread t1 = new Thread(
                 new Runnable() {
                     @Override
                     public void run() {
                         count.synMethod();
                     }
                 }, "t1");
 
         // 新建t2, t2会调用“count对象”的nonSynMethod()方法
         Thread t2 = new Thread(
                 new Runnable() {
                     @Override
                     public void run() {
                         count.nonSynMethod();
                     }
                 }, "t2");  
 
 
         t1.start();  // 启动t1
         t2.start();  // 启动t2
     } 
 }
  

运行结果:

t1 synMethod loop 0
t1 synMethod loop 1
t1 synMethod loop 2
t1 synMethod loop 3
t1 synMethod loop 4
t2 nonSynMethod loop 0
t2 nonSynMethod loop 1
t2 nonSynMethod loop 2
t2 nonSynMethod loop 3
t2 nonSynMethod loop 4
 

结果说明:
主线程中新建了两个子线程t1和t2。t1和t2运行时都调用synchronized(this),这个this是Count对象(count),而t1和t2共用count。因此,在t1运行时,t2会被阻塞,等待t1运行释放“count对象的同步锁”,t2才能运行。

 

3. synchronized方法 和 synchronized代码块

“synchronized方法”是用synchronized修饰方法,而 “synchronized代码块”则是用synchronized修饰代码块。

synchronized方法示例

public synchronized void foo1() {
    System.out.println("synchronized methoed");
}

synchronized代码块

public void foo2() {
    synchronized (this) {
        System.out.println("synchronized methoed");
    }
}

synchronized代码块中的this是指当前对象。也可以将this替换成其他对象,例如将this替换成obj,则foo2()在执行synchronized(obj)时就获取的是obj的同步锁。


synchronized代码块可以更精确的控制冲突限制访问区域,有时候表现更高效率。下面通过一个示例来演示:

 // Demo4.java的源码
 public class Demo4 {
 
     public synchronized void synMethod() {
         for(int i=0; i<1000000; i++)
             ;
     }
 
     public void synBlock() {
         synchronized( this ) {
             for(int i=0; i<1000000; i++)
                 ;
         }
     }
 
     public static void main(String[] args) {
         Demo4 demo = new Demo4();
 
         long start, diff;
         start = System.currentTimeMillis();                // 获取当前时间(millis)
         demo.synMethod();                                // 调用“synchronized方法”
         diff = System.currentTimeMillis() - start;        // 获取“时间差值”
         System.out.println("synMethod() : "+ diff);
         
         start = System.currentTimeMillis();                // 获取当前时间(millis)
         demo.synBlock();                                // 调用“synchronized方法块”
         diff = System.currentTimeMillis() - start;        // 获取“时间差值”
         System.out.println("synBlock()  : "+ diff);
     }
 }
  

(某一次)执行结果:

synMethod() : 11
synBlock() : 3

 

4. 实例锁 和 全局锁

实例锁 -- 锁在某一个实例对象上。如果该类是单例,那么该锁也具有全局锁的概念。
               实例锁对应的就是synchronized关键字。
全局锁 -- 该锁针对的是类,无论实例多少个对象,那么线程都共享该锁。
               全局锁对应的就是static synchronized(或者是锁在该类的class或者classloader对象上)。

关于“实例锁”和“全局锁”有一个很形象的例子:

pulbic class Something {
    public synchronized void isSyncA(){}
    public synchronized void isSyncB(){}
    public static synchronized void cSyncA(){}
    public static synchronized void cSyncB(){}
}

假设,Something有两个实例x和y。分析下面4组表达式获取的锁的情况。
(01) x.isSyncA()与x.isSyncB() 
(02) x.isSyncA()与y.isSyncA()
(03) x.cSyncA()与y.cSyncB()
(04) x.isSyncA()与Something.cSyncA()

(01) 不能被同时访问。因为isSyncA()和isSyncB()都是访问同一个对象(对象x)的同步锁!

  // LockTest1.java的源码
  class Something {
      public synchronized void isSyncA(){
          try {  
              for (int i = 0; i < 5; i++) {
                  Thread.sleep(100); // 休眠100ms
                  System.out.println(Thread.currentThread().getName()+" : isSyncA");
              }
          }catch (InterruptedException ie) {  
         }  
     }
     public synchronized void isSyncB(){
         try {  
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(100); // 休眠100ms
                 System.out.println(Thread.currentThread().getName()+" : isSyncB");
             }
         }catch (InterruptedException ie) {  
         }  
     }
 }
 
 public class LockTest1 {
 
     Something x = new Something();
     Something y = new Something();
 
     // 比较(01) x.isSyncA()与x.isSyncB() 
     private void test1() {
         // 新建t11, t11会调用 x.isSyncA()
         Thread t11 = new Thread(
                 new Runnable() {
                     @Override
                     public void run() {
                         x.isSyncA();
                     }
                 }, "t11");
          // 新建t12, t12会调用 x.isSyncB()
         Thread t12 = new Thread(
                 new Runnable() {
                     @Override
                     public void run() {
                         x.isSyncB();
                     }
                 }, "t12");  
 
 
         t11.start();  // 启动t11
         t12.start();  // 启动t12
     }
 
     public static void main(String[] args) {
         LockTest1 demo = new LockTest1();
         demo.test1();
     }
 }

 

 

运行结果:

t11 : isSyncA
t11 : isSyncA
t11 : isSyncA
t11 : isSyncA
t11 : isSyncA
t12 : isSyncB
t12 : isSyncB
t12 : isSyncB
t12 : isSyncB
t12 : isSyncB
 

 

(02) 可以同时被访问。因为访问的不是同一个对象的同步锁,x.isSyncA()访问的是x的同步锁,而y.isSyncA()访问的是y的同步锁。

 // LockTest2.java的源码
 class Something {
     public synchronized void isSyncA(){
         try {  
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(100); // 休眠100ms
                 System.out.println(Thread.currentThread().getName()+" : isSyncA");
             }
         }catch (InterruptedException ie) {  
         }  
     }
     public synchronized void isSyncB(){
         try {  
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(100); // 休眠100ms
                 System.out.println(Thread.currentThread().getName()+" : isSyncB");
             }
         }catch (InterruptedException ie) {  
         }  
     }
     public static synchronized void cSyncA(){
         try {  
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(100); // 休眠100ms
                 System.out.println(Thread.currentThread().getName()+" : cSyncA");
             } 
         }catch (InterruptedException ie) {  
         }  
     }
     public static synchronized void cSyncB(){
         try {  
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(100); // 休眠100ms
                 System.out.println(Thread.currentThread().getName()+" : cSyncB");
             } 
         }catch (InterruptedException ie) {  
         }  
     }
 }
 
 public class LockTest2 {
 
     Something x = new Something();
     Something y = new Something();
 
     // 比较(02) x.isSyncA()与y.isSyncA()
     private void test2() {
         // 新建t21, t21会调用 x.isSyncA()
         Thread t21 = new Thread(
                 new Runnable() {
                     @Override
                     public void run() {
                         x.isSyncA();
                     }
                 }, "t21");
 
         // 新建t22, t22会调用 x.isSyncB()
         Thread t22 = new Thread(
                 new Runnable() {
                     @Override
                     public void run() {
                         y.isSyncA();
                     }
                 }, "t22");  
 
 
         t21.start();  // 启动t21
         t22.start();  // 启动t22
     }
 
     public static void main(String[] args) {
         LockTest2 demo = new LockTest2();
 
         demo.test2();
     }
 }
  

运行结果:

t21 : isSyncA
t22 : isSyncA
t21 : isSyncA
t22 : isSyncA
t21 : isSyncA
t22 : isSyncA
t21 : isSyncA
t22 : isSyncA
t21 : isSyncA
t22 : isSyncA
 

 

(03) 不能被同时访问。因为cSyncA()和cSyncB()都是static类型,x.cSyncA()相当于Something.isSyncA(),y.cSyncB()相当于Something.isSyncB(),因此它们共用一个同步锁,不能被同时反问。

 // LockTest3.java的源码
 class Something {
     public synchronized void isSyncA(){
         try {  
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(100); // 休眠100ms
                 System.out.println(Thread.currentThread().getName()+" : isSyncA");
             }
         }catch (InterruptedException ie) {  
         }  
     }
     public synchronized void isSyncB(){
         try {  
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(100); // 休眠100ms
                 System.out.println(Thread.currentThread().getName()+" : isSyncB");
             }
         }catch (InterruptedException ie) {  
         }  
     }
     public static synchronized void cSyncA(){
         try {  
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(100); // 休眠100ms
                 System.out.println(Thread.currentThread().getName()+" : cSyncA");
             } 
         }catch (InterruptedException ie) {  
         }  
     }
     public static synchronized void cSyncB(){
         try {  
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(100); // 休眠100ms
                 System.out.println(Thread.currentThread().getName()+" : cSyncB");
             } 
         }catch (InterruptedException ie) {  
         }  
     }
 }
 
 public class LockTest3 {
 
     Something x = new Something();
     Something y = new Something();
 
     // 比较(03) x.cSyncA()与y.cSyncB()
     private void test3() {
         // 新建t31, t31会调用 x.isSyncA()
         Thread t31 = new Thread(
                 new Runnable() {
                     @Override
                     public void run() {
                         x.cSyncA();
                     }
                 }, "t31");
 
         // 新建t32, t32会调用 x.isSyncB()
         Thread t32 = new Thread(
                 new Runnable() {
                     @Override
                     public void run() {
                         y.cSyncB();
                     }
                 }, "t32");  
 
 
         t31.start();  // 启动t31
         t32.start();  // 启动t32
     }
 
     public static void main(String[] args) {
         LockTest3 demo = new LockTest3();
 
         demo.test3();
     }
 }
  

运行结果:

t31 : cSyncA
t31 : cSyncA
t31 : cSyncA
t31 : cSyncA
t31 : cSyncA
t32 : cSyncB
t32 : cSyncB
t32 : cSyncB
t32 : cSyncB
t32 : cSyncB
 

 

(04) 可以被同时访问。因为isSyncA()是实例方法,x.isSyncA()使用的是对象x的锁;而cSyncA()是静态方法,Something.cSyncA()可以理解对使用的是“类的锁”。因此,它们是可以被同时访问的。

  // LockTest4.java的源码
  class Something {
      public synchronized void isSyncA(){
          try {  
              for (int i = 0; i < 5; i++) {
                  Thread.sleep(100); // 休眠100ms
                  System.out.println(Thread.currentThread().getName()+" : isSyncA");
              }
          }catch (InterruptedException ie) {  
         }  
     }
     public synchronized void isSyncB(){
         try {  
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(100); // 休眠100ms
                 System.out.println(Thread.currentThread().getName()+" : isSyncB");
             }
         }catch (InterruptedException ie) {  
         }  
     }
     public static synchronized void cSyncA(){
         try {  
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(100); // 休眠100ms
                 System.out.println(Thread.currentThread().getName()+" : cSyncA");
             } 
         }catch (InterruptedException ie) {  
         }  
     }
     public static synchronized void cSyncB(){
         try {  
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(100); // 休眠100ms
                 System.out.println(Thread.currentThread().getName()+" : cSyncB");
             } 
         }catch (InterruptedException ie) {  
         }  
     }
 }
 
 public class LockTest4 {
 
     Something x = new Something();
     Something y = new Something();
 
     // 比较(04) x.isSyncA()与Something.cSyncA()
     private void test4() {
         // 新建t41, t41会调用 x.isSyncA()
         Thread t41 = new Thread(
                 new Runnable() {
                     @Override
                     public void run() {
                         x.isSyncA();
                     }
                 }, "t41");
 
         // 新建t42, t42会调用 x.isSyncB()
         Thread t42 = new Thread(
                 new Runnable() {
                     @Override
                     public void run() {
                         Something.cSyncA();
                     }
                 }, "t42");  
 
 
         t41.start();  // 启动t41
         t42.start();  // 启动t42
     }
 
     public static void main(String[] args) {
         LockTest4 demo = new LockTest4();
 
         demo.test4();
     }
 }
 

运行结果:

t41 : isSyncA
t42 : cSyncA
t41 : isSyncA
t42 : cSyncA
t41 : isSyncA
t42 : cSyncA
t41 : isSyncA
t42 : cSyncA
t41 : isSyncA
t42 : cSyncA
 

转载自:http://www.cnblogs.com/skywang12345/p/3479202.html

《Scratch图形化等级考试(1~4级)历届真题解析》专栏总目录 ❤️ 专栏名称:《🌸 专栏介绍:中国电子学会《全国青少年软件编程等级考试》Scratch图形化等级考试(1~4级)历届真题解析。🚀 订阅专栏:原价 99.9,🔥 火爆订阅中 🔥,限时 19.9。订阅后可阅读专栏内所有文章,本专栏持续更新中,欢迎订阅! 阅读详情

相关推荐

【Qualcomm高通音频】音效调试_录音文件播放有杂音,如何定位原因?

一、录音播放数据处理过程介绍 (1)TX方向 麦克风(硅麦克风或者主机体麦克风)采集模拟音频信号,经过内部CODEC芯片中的adc转换为数字信号,在经过高通音频DSP处理音效后编码为wav/aac/amr/mp3等格式文件。 (2)RX方向 音频文件经过解码、重采样还原为pcm数据,经过DSP处理音效后送到内部CODEC,然后经过DAC转换为模拟信号,送到喇叭。 二、分析步骤 1...

crow_ch的博客 5976

JAVA多线程之间实现同步+多线程并发同步解决方案

一、什么是线程安全问题 为什么有线程安全问题?       当多个线程同时共享同一个全局变量或静态变量,做写的操作(修改变量值)时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作时不会发生数据冲突问题。案例:需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果。/** * 需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果。 * Crea...

yz2015的博客 4万+

苍穹外卖项目面试总结话术

美食速递这个项目最初是我参与制作的大创项目,是一款为中南学生提供校园外卖送至宿舍服务的软件,包含系统管理后台和小程序端两部分。其中系统管理后台主要提供给食堂内部员工使用,可以对食堂各个窗口、员工、订单、菜品等进行维护管理;小程序端可以在线浏览菜品、添加购物车、下单等,由学生兼职做跑腿送餐上门服务。这是个前后端分离的项目,我主要是负责后端的用户登录、员工管理,菜品管理,订单管理模块的编码实现。

qq_45195447的博客 1万+

Java 多线程同步:Synchronized 关键字

内置锁 每个Java对象都对应着一个实现同步的锁,这个锁就是内置锁。之所以每个对象都有一个内置锁,是为了免去显式地创建锁对象。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁。 Java内置锁是一个互斥锁,这就是意味着最多只有一个线程能够获得该锁,当线程A尝试去获得线程B持有的内置锁时,线程A必须等待或者阻塞,直到线程B释放这个锁,如果B线程不释放这个锁,那么A线程将永远等待下去。 同步方法和同步代码块 对象锁 // 普通同步方法 public synchron

xufei5789651的博客 665

Speedtree学习笔记(案例)——拥有多种材质的植物如何导入使用(以草为例)

注:Speedtree无论保存还是导入模型其存储路径不可有中文。 第一步拆分草的模型 根据所需的材质去拆分(例:假若草的果实,茎秆和叶子是不同的材质那么就需拆分为三份;假若画的全部颜色及材质一样就没有必要去拆分模型) 第二步导入草的模型 在Mesh面板中依次导入草的模型——Do nothing additional right now 第三步扩大草的生长区域范围(可省略)...

L人青的博客 5722

Hypermesh2021实战:塑料圆盘结构化网格划分全流程(附避坑指南)

本文详细介绍了使用Hypermesh2021进行塑料圆盘结构化网格划分的全流程操作,包括几何预处理、网格生成策略及质量验证。特别针对工程实践中常见的12个典型问题提供解决方案,帮助用户提升CAE仿真分析的精度和效率。

weixin_29294597的博客 320

线程同步——使用(synchronized)关键字

1.需要线程同步的原因: Java 中允许多线程并行访问,同一时间段内多个线程同时完成各自的操作。但是多个线程同时操作同一个共享数据时,可能会导致数据不准确的问题。 2.线程同步的方法: 可以通过 synchronized 关键字修饰方法实现线程同步,每个Java 对象都有一个内置锁,内置锁会保护使用 synchronized 关键字修饰的方法,要调用该方法就必须先获得锁,否则就处于阻塞状态。 3。synchronized 关键字可以修饰实例方法,也可以修饰静态方法,两者在使用的时候是有区别的。 (1)给实

wu6668的博客 1979

【SAP PO】SAP PO 接口配置完整教程之二REST服务对接

SAP PO 接口配置完整教程之二REST服务对接

XLevon的博客 1万+

多线程同步synchronized关键字

同步块 :synchronized(object){ 共享的内容 } object 为任意一个对象,每一个对象都存在一个标记位,并具有两个值 :0,1。 一个线程运行到同步块时首先检查该对象的标记位,如果为0状态,表明此同步块中存在其他线程在运行。这时该线程就处于就绪状态,直到处于同步块中的线程执行完同步块中的代码为止。这时该对象的标志位被设置为1,该线程才能执行同步块中的代码,并将object对象的标志位设置为0,防止其他线程执行同步块中的代码。 同步方法:syn...

qq_50145440的博客 166

二维紧束缚模型求解程序

假如我们已经推导出了二维紧束缚模型的哈密顿量矩阵H(kx,ky)的解析形式,那么在整个布里渊区对角化矩阵就可以得到能带。从技术上说这里面有以下几个问题。 1. 缺少实空间和倒空间的坐标,使得能带难以和布里渊区高对称点对应。 2. 最容易处理的布里渊区是矩形,对于其他多边形,如果全布里渊区mesh画费米面有一定技术困难。 因此一个好的处理框架是首先给出实空间原子坐标,给出实空间哈密顿量,...

wwxy1995的博客 4085

实战分享:如何利用svchost进程绕过360防护(附完整Shellcode注入教程)

本文深入解析系统进程安全防护机制,探讨svchost等关键进程的安全特性与防护策略。详细分析安全软件的行为检测和内存保护技术,提供系统加固与监控实践建议,助力企业构建多层次防御体系,有效应对潜在安全威胁。

weixin_30752699的博客 99

java多线程-synchronized关键字详解

java多线程-synchronized关键字详解

二萌的博客 593

华为OD机试 - 商品推荐多属性排序 - 数组(Python/JS/C/C++ 双机位A卷 100分)

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。双十一来临,小王准备买某个购物平台买坚果。在输入坚果时,页面默认按照综合推荐列表。小王想知道这个综合排序时如何完成的,于是便开始思考算法题。经过一番操作后,完成它的多个关键词排序算法。希望你给小王提供一份正确的排序结果,验证其实现算法结果的准确性

学Java,找哪吒 623

多线程:synchronized关键字详解

实际上,在多线程环境中,难免会出现多个线程对一个对象的实例变量进行同时访问和操作,如果编程处理不当,会产生脏读现象。我们先来看一个简单的线程安全问题的例子!count++;@Overridej++) {// 初始化数据实体//使用多线程编程对数据进行计算i < 10;i++) {try {多次运行结果如下:第一次运行:result: 9788554第二次运行:result: 9861461第三次运行:result: 6412249...

rc1596919047的博客 855

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Java多线程之synchronized关键字全面总结2.0

为了避免出现上一张的结果,那么Java就是用了synchronized关键字。 再使用了synchronized关键字之后 一个类的实例如果想调用锁住的代码,那么这个实例必须要能够拿到对应的锁才行。而一个锁只能同时被一个实例拿到。 那么判断的根本依据就在于:实例需要拿到的是不是同一个锁! 如果是同一个锁,那么对应代码就不能同时执行,如果不是同一个锁,那么对应的代码就可以同时执行。 他有四种情...

bbqe597的博客 282

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Java多线程 synchronized关键字

1、在Java多线程中,没用使用synchronized关键字:// 业务类 class Example { // threadName 线程名称 public void executeOne(String threadName) { for (int i = 0; i < 10; ++i) { try { Thread.s

chunxuexm的专栏 601

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Java 多线程(六) synchronized关键字详解

Java 多线程(六) synchronized关键字详解 Java 多线程(六) synchronized关键字详解   多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题。   同步机制可以使用synchronized关键字实现。   当synchronized关键字修饰一个方法的时候,...

pxs666的博客 98

Java 多线程 synchronized关键字详解

多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题。 同步机制可以使用synchronized关键字实现。 当synchronized关键字修饰一个方法的时候,该方法叫做同步方法。 当synchronized方法执行完或发生异常时,会自动释放锁。 下面通过一个例子来对synchronized关键字的用法进行解析。 1.是否使用synchronized关键字的不同 public class ThreadTest { public s

weixin_53341657的博客 189

多线程之synchronized 关键字的用法

初识 synchronized 关键字 synchronized 提供了一种排他机制,也就是在同一时间只能有一个线程执行某些操作。也就是说如果多个线程对index变量(共享变量/资源同时操作)而引起的数据不一致的问题,我们可以使用该关键字去解决。 什么是 synchronized? synchronized 关键字可以实现一个简单的策略来防止线程干扰 和内存一致性错误,如果一个对象对多个线程是可见的,那么对该对象的所有读或者写都将通过同步的方式来进行。 synchronized 关键字的用法 synchro

wjf_jone的博客 412

Java 多线程:synchronized 多线程同步关键字

前言在 多线程生成的原因(Java内存模型与i++操作解析) 中,介绍了Java的内存模型,从而可能导致的多线程问题。synchronized就是避免这个问题的解决方法之一。除了 synchronized 的方式,还有 lock,condition,volatile,threadlocal,atomicInteger,cas等方式。synchronized 用法它的修饰对象有几种: 1. 修饰一个

不更新了 1150

JAVA多线程之关键字synchronized

synchronized本意是同步的意思,那么就要先说一下同步的概念了 所谓的同步是指所有的线程不是同时进入到方法中,而是按照顺序一个一个进入方法执行。 使用synchronized处理有两种模式:同步代码块和同步方法 ...

L_R 308

java多线程关键字synchronized用法

相信大家在开发中肯定会用到多线程的知识,而"synchronized"关键字肯定会用到的,这个修饰符在多线程里用来同步的,就是上锁的对象对应的方法或者代码块同一段时间内只能被一个线程调用,其他的线程就要等待。 java里面每个对象都有一把锁,当线程访问这个对象监视的方法或者代码块时,就会给这个对象上锁,访问结束后解锁,其他等待的线程方能访问这些同步的方法或者代码块。 注意:"sync.........

Alex老夫子的专栏 1195

Java 多线程(二) Synchronized与Volatile关键字

前言 在上章中,我们介绍了Java Thread API.本章我们介绍下Java中的Synchronized与Volatile关键字. 在本章中,我们将介绍如下的几个模块: Synchronized关键字 线程安全问题 synchronized 关键字的使用 对象锁与类锁 Synchronized关键字修饰final类型的变量 & 静态变量 Volatile关键字 Volatil...

Be yourself. 816

Java多线程同步 synchronized 关键字的使用

代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D)运行完这个方法后再运行此线程A,没有的话,直接运行它包括两种用法:synchronized 方法和 synchronized 块。 JAVA多线程买票案例 synchronized 同步 用synchroni...

dht91597的博客 178

Java多线程 —— synchronized关键字详解

一、多线程的同步 1、为什么要引入同步机制 在多线程环境中,可能会有两个甚至更多的线程试图同时访问一个有限的资源。必须对这种潜在资源冲突进行预防。 解决方法:在线程使用一个资源时为其加锁即可。 访问资源的第一个线程为其加上锁以后,其他线程便不能再使用那个资源,除非被解锁。 2、实例 用一个取钱的程序例子,来说明为什么需要引入同步。在使用同步机制前,整体程序如下: package com.demo;...

qq_42499816的博客 394

synchronized关键字解决多线程并发安全问题

线程:单一的顺序执行流程就是一个线程,顺序执行:代码一句一句的先后执行。多线程:多个线程并发执行。线程之间的代码是快速被CPU切换执行的,造成一种感官上"同时"执行的效果。

weixin_52007132的博客 1375
上一篇: 多线程-线程两种实现方法(继承类、实现接口)
下一篇: 多线程-线程等待与唤醒
Mark_XC
博客等级 码龄9年 16粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值