Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

五、以上规则对其它对象锁同样适用.

举例说明: 

     一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

package ths;

public class Thread1 implements Runnable { 

     public void run() { 

          synchronized(this) { 

               for (int i = 0; i < 5; i++) { 

                    System.out.println(Thread.currentThread().getName() + " synchronized loop " + i); 


               } 

          } 

     } 

     public static void main(String[] args) { 

          Thread1 t1 = new Thread1(); 

          Thread ta = new Thread(t1, "A"); 

          Thread tb = new Thread(t1, "B"); 

          ta.start(); 

          tb.start(); 

     }

}

结果: 

     A synchronized loop 0 

     A synchronized loop 1 

     A synchronized loop 2 

     A synchronized loop 3 

     A synchronized loop 4 

     B synchronized loop 0 

     B synchronized loop 1 

     B synchronized loop 2 

     B synchronized loop 3 

     B synchronized loop 4

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

package ths;

public class Thread2 { 

     public void m4t1() { 

          synchronized(this) { 

               int i = 5; 

               while( i-- > 0) { 

                    System.out.println(Thread.currentThread().getName() + " : " + i); 


                    try { 

                         Thread.sleep(500); 

                    } catch (InterruptedException ie) { 

                    } 

               } 

          } 

     } 

     public void m4t2() { 

          int i = 5; 

          while( i-- > 0) { 

               System.out.println(Thread.currentThread().getName() + " : " + i); 


               try { 

                    Thread.sleep(500); 

               } catch (InterruptedException ie) { 

               } 

          } 

     } 

     public static void main(String[] args) { 

          final Thread2 myt2 = new Thread2(); 

          Thread t1 = new Thread(  new Runnable() {  public void run() {  myt2.m4t1();  }  }, "t1"  ); 


          Thread t2 = new Thread(  new Runnable() {  public void run() { myt2.m4t2();   }  }, "t2"  ); 


          t1.start(); 

          t2.start(); 

     }

}

结果: 

     t1 : 4 

     t2 : 4 

     t1 : 3 

     t2 : 3 

     t1 : 2 

     t2 : 2 

     t1 : 1 

     t2 : 1 

     t1 : 0 

     t2 : 0

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

//修改Thread2.m4t2()方法: 

     public void m4t2() { 

          synchronized(this) { 

               int i = 5; 

               while( i-- > 0) { 

                    System.out.println(Thread.currentThread().getName() + " : " + i); 


                    try { 

                         Thread.sleep(500); 

                    } catch (InterruptedException ie) { 

                    } 

               } 

          }

}

结果:

t1 : 4 

     t1 : 3 

     t1 : 2 

     t1 : 1 

     t1 : 0 

     t2 : 4 

     t2 : 3 

     t2 : 2 

     t2 : 1 

     t2 : 0

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

//修改Thread2.m4t2()方法如下:

public synchronized void m4t2() { 

          int i = 5; 

          while( i-- > 0) { 

               System.out.println(Thread.currentThread().getName() + " : " + i); 


               try { 

                    Thread.sleep(500); 

               } catch (InterruptedException ie) { 

               } 

          } 

     }

结果: 

     t1 : 4 

     t1 : 3 

     t1 : 2 

     t1 : 1 

     t1 : 0 

     t2 : 4 

     t2 : 3 

     t2 : 2 

     t2 : 1 

     t2 : 0

五、以上规则对其它对象锁同样适用:

package ths;

public class Thread3 {

     class Inner {

          private void m4t1() {

               int i = 5;

               while(i-- > 0) {

                    System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i);


                    try {

                         Thread.sleep(500);

                    } catch(InterruptedException ie) {

                    }

               }

          }

          private void m4t2() {

               int i = 5;

               while(i-- > 0) {

                    System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);


                    try {

                         Thread.sleep(500);

                    } catch(InterruptedException ie) {

                    }

               }

          }

     }

     private void m4t1(Inner inner) {

          synchronized(inner) { //使用对象锁

          inner.m4t1();

     }

     private void m4t2(Inner inner) {

          inner.m4t2();

     }

     public static void main(String[] args) {

          final Thread3 myt3 = new Thread3();

          final Inner inner = myt3.new Inner();

          Thread t1 = new Thread( new Runnable() {public void run() { myt3.m4t1(inner);} }, "t1");


     Thread t2 = new Thread( new Runnable() {public void run() { myt3.m4t2(inner);} }, "t2");


     t1.start();

     t2.start();

  }

}

结果:

尽管线程t1获得了对Inner的对象锁,但由于线程t2访问的是同一个Inner中的非同步部分。所以两个线程互不干扰。

t1 : Inner.m4t1()=4 

     t2 : Inner.m4t2()=4 

     t1 : Inner.m4t1()=3 

     t2 : Inner.m4t2()=3 

     t1 : Inner.m4t1()=2 

     t2 : Inner.m4t2()=2 

     t1 : Inner.m4t1()=1 

     t2 : Inner.m4t2()=1 

     t1 : Inner.m4t1()=0 

     t2 : Inner.m4t2()=0

现在在Inner.m4t2()前面加上synchronized:

private synchronized void m4t2() { 

          int i = 5; 

          while(i-- > 0) { 

               System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i); 


               try { 

                    Thread.sleep(500); 

               } catch(InterruptedException ie) { 

               } 

          } 

     }

结果:

尽管线程t1与t2访问了同一个Inner对象中两个毫不相关的部分,但因为t1先获得了对Inner的对象锁,所以t2对Inner.m4t2()的访问也被阻塞,因为m4t2()是Inner中的一个同步方法。

t1 : Inner.m4t1()=4 

     t1 : Inner.m4t1()=3 

     t1 : Inner.m4t1()=2 

     t1 : Inner.m4t1()=1 

     t1 : Inner.m4t1()=0 

     t2 : Inner.m4t2()=4 

     t2 : Inner.m4t2()=3 

     t2 : Inner.m4t2()=2 

     t2 : Inner.m4t2()=1 

     t2 : Inner.m4t2()=0

第二篇:

synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。 

1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如: 

public synchronized void accessVal(int newVal); 

synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能

执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行

状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有

一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)

。 

在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成

员变量的访问。 

synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为

synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可

以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供

了更好的解决办法,那就是 synchronized 块。 

2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下: 

synchronized(syncObject) { 

//允许访问控制的代码 

}

Java synchonized 同步的更多相关文章

  1. java多线程-同步块

    Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java 同步块用来避免竞争.本文介绍以下内容: Java 同步关键字(synchronzied) 实例方法同步 ...

  2. 一篇搞定RSA加密与SHA签名|与Java完全同步

    基础知识 什么是RSA?答:RSA是一种非对称加密算法,常用来对传输数据进行加密,配合上数字摘要算法,也可以进行文字签名. RSA加密中padding?答:padding即填充方式,由于RSA加密算法 ...

  3. Java多线程同步问题的探究

    一.线程的先来后到——问题的提出:为什么要有多线程同步?Java多线程同步的机制是什么? http://www.blogjava.net/zhangwei217245/archive/2010/03/ ...

  4. java 线程同步 原理 sleep和wait区别

    java线程同步的原理java会为每个Object对象分配一个monitor, 当某个对象(实例)的同步方法(synchronized methods)被多个线程调用时,该对象的monitor将负责处 ...

  5. Java线程同步_1

    Java线程同步_1 synchronized 该同步机制的的核心是同步监视器,任何对象都可以作为同步监视器,代码执行结束,或者程序调用了同步监视器的wait方法会导致释放同步监视器 synchron ...

  6. 转:关于JAVA多线程同步

    转:http://lanvis.blog.163.com/blog/static/26982162009798422547/ 因为需要,最近关注了一下JAVA多线程同步问题.JAVA多线程同步主要依赖 ...

  7. java多线程同步

    一篇好文:java多线程机制同步原则 概括起来说,Java 多线程同步机制主要包含如下几点:1:如果一个类包含一个或几个同步方法,那么由此类生成的每一个对象都配备一个队列用来容纳那些等待执行同步的线程 ...

  8. java多线程——同步块synchronized详解

    Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java同步块用来避免竞争.本文介绍以下内容: Java同步关键字(synchronzied) 实例方法同步 静 ...

  9. Java线程同步之一--AQS

    Java线程同步之一--AQS 线程同步是指两个并发执行的线程在同一时间不同时执行某一部分的程序.同步问题在生活中也很常见,就比如在麦当劳点餐,假设只有一个服务员能够提供点餐服务.每个服务员在同一时刻 ...

随机推荐

  1. XenServer删除ISO存储!

    1.用命令 df -hal 可以看到 ISO库是使用了10G的硬盘的 2.下面开始直接右键删除ISO,但看到资源还是占用着10G的 3.如果想把这10G的硬盘资源空出来的话,只要复制前面查找到挂载的路 ...

  2. <C#任务导引教程>练习五

    //27,创建一个控制台应用程序,声明两个DateTime类型的变量dt,获取系统的当前日期时间,然后使用Format格式化进行规范using System;class Program{    sta ...

  3. [cf582E]Boolean Function

    由于每一个运算都有括号,因此添加的运算不会改变运算顺序 先将其建出一棵表达式树,也就是维护两个栈,是节点和运算符优先级单调递增的栈(设置左括号优先级最低,右括号弹出直至左括号) 每一次运算,也就是新建 ...

  4. 高并发异步解耦利器:RocketMQ究竟强在哪里?

    上篇文章消息队列那么多,为什么建议深入了解下RabbitMQ?我们讲到了消息队列的发展史: 并且详细介绍了RabbitMQ,其功能也是挺强大的,那么,为啥又要搞一个RocketMQ出来呢?是重复造轮子 ...

  5. python中使用正则表达式处理文本(仅记录常用方法和参数)

    标准库模块 python中通过re模块使用正则表达式 import re 常用方法 生成正则表达式对象 compile(pattern[,flags]) pattern:正则表达式字符串 flags: ...

  6. MariaDB—配置允许(别的电脑IP)远程访问方式

    首先配置允许访问的用户,采用授权的方式给用户权限 1 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'IDENTIFIED BY '123456' WITH GRAN ...

  7. Perl哈希%hash

    哈希是 key/value 键/值对的集合. Perl中哈希变量以百分号 (%) 标记开始. 访问哈希元素格式:${key}. 以下是一个简单的哈希实例: 实例 #!/usr/bin/perl %da ...

  8. Python time&datetime模块

    1.time&datetime模块 time&datetime是时间模块,常用以处理时间相关问题 time.time() #返回当前时间的时间戳timestamp time.sleep ...

  9. SPI详解2

    串行外设接口 (SPI) 总线是一种运行于全双工模式下的同步串行数据链路.用于在单个主节点和一个或多个从节点之间交换数据. SPI 总线实施简单,仅使用四条数据信号线和控制信号线(请参见图 1). 图 ...

  10. 🚀 RabbitMQ课程发布-KuangStudy

    RabbitMQ课程上线(44集) 视频教程地址:https://www.kuangstudy.com/course/detail/1323452886432944129 专栏地址:https://w ...