Java线程同步(含详细解释/代码实例)

简介: Java线程同步(含详细解释/代码实例)

一、为解决线程安全问题,Java引入监视器(monitor)来保证共享数据的同步性。任何对象都可作为一个监视器,关键词synchronized修饰某个对象后,该对象就成为监视器。

二、同步代码块只能有一个线程独占执行。

三、同步代码块作用:多个线程第共享资源操作容易引起冲突,这些容易引起冲突的代码块称之为临界区,在临界区通过引入监视器,并用synchronized使多个线程在临界区同步起来,从而避免可能引起的冲突。

四、Synchronized的三种用法:

       1、synchronized代码块:监视器为指定的对象。

       2、synchronized方法:监视器为this对象。

       3、synchronized静态方法:监视器为相应的类。

一、关键词synchronized加在run方法前

代码展示:

class Resource implements Runnable{
    volatile public int i;
    public Resource(int _i){
        i=_i;
    }
    public synchronized void run(){ //关键词synchronized加在run方法前
        while(true){
                if(i>0){
                    try{Thread.sleep(200);}
                    catch (Exception e){}
                        i--;
                        System.out.println(Thread.currentThread().getName()+" "+i);
                    }
                else{
                    System.out.println(Thread.currentThread().getName());
                    break;
                }
        }
    }
}
public class TestSecurity {
    public static void main(String[] args){
        Resource m=new Resource(4);
        Thread t1=new Thread(m);
        Thread t2=new Thread(m);
        t1.start();
        t2.start();
    }
}

image.gif

运行结果如下:

image.gif编辑

补充说明:本程序仅Thread-0完成了i的自减过程,因关键字synchronized加在run()方法前,监视器为Resource对象。系统调度的结果使Thread-0在此刻先获得了Resource监视权,在没有完成Resource对象run方法调用前,Thread-1线程无法获得该监视器所有权

二、synchronized代码块

代码展示:

class Resource1 implements Runnable{
    volatile public int i;
    volatile public Integer it;
    public Resource1(int _i){
        i=_i;
        it=new Integer(i);//new 一个Integer对象的时候,实际上是生成了一个指针指向此对象;
    }
    public  void run(){
        while(true){
            synchronized (it) {//synchronized代码块
                if (i > 0) {
                    try {
                        Thread.sleep(200);
                    } 
                    catch (Exception e) {}
                    i--;
                    System.out.println(Thread.currentThread().getName() + " " + i);
                }
                else {
                    System.out.println(Thread.currentThread().getName());
                    break;
                }
            }
        }
    }
}
public class TestSecurity1 {
    public static void main(String[] args){
        Resource1 m=new Resource1(4);
        Thread t1=new Thread(m);
        Thread t2=new Thread(m);
        t1.start();
        t2.start();
    }
}

image.gif

运行结果如下:

image.gif编辑

补充说明:此代码增加了一个Resource对象的属性it,它引用一个对象,此对象充当监视器,用synchronized(it)表示,并构成一个同步代码块。当“Thread-1”执行到synchronized(it)代码块时,其获得了该监视权,“Thread-1”未执行完同步代码,“Thread-0”因无法获得监视权而不能进入同步代码块。“Thread-1”执行完同步代码块后,释放监视权,“Thread-0”获得监视权后执行同步代码块,这就实现了两个线程对共享资源操作的同步。

目录
相关文章
|
4天前
|
Java
【专栏】Java中的反射机制与应用实例
【4月更文挑战第27天】本文探讨了Java反射机制,该机制允许程序在运行时获取类信息、动态创建对象、调用方法和访问属性。反射通过Class、Constructor、Method和Field类实现。文中列举了反射的应用场景,如动态创建对象、调用方法、访问属性和处理注解,并提供了相关实例代码演示。
|
1天前
|
Java Spring
Java 效率编码 必备插件 Lombok 让代码更优雅
该内容是一个关于Lombok插件的教程摘要:介绍了Lombok用于减少Java开发中的模板代码,提升效率;讲解了如何在IntelliJ IDEA中安装Lombok插件,以及在pom.xml中添加依赖;并提到了@Data注解能自动生成getter/setter、equals、hashCode和toString方法,@Slf4j注解自动处理日志,@Builder用于构建对象,以及@AllArgsConstructor和@NoArgsConstructor注解生成构造函数。还鼓励探索更多Lombok的注解用法。
|
1天前
|
Java 关系型数据库 测试技术
Java代码一键生成数据库文档(案例详解)
Screw是一个自动化数据库文档生成工具,能根据数据库表结构快速生成简洁、多格式(HTML、Word、Markdown)的文档,支持MySQL、MariaDB等多数据库。它使用Freemarker模板,允许用户自定义样式。依赖包括HikariCP数据库连接池和对应JDBC驱动。通过在Java代码或Maven插件中配置,可方便生成文档。示例代码展示了如何在测试用例中使用Screw。文档效果依赖于数据库中的表和字段注释。
|
1天前
|
NoSQL Java API
java一行代码实现RESTFul接口
Spring Data REST是构建在Spring Data之上的库,可自动将repository转换为REST服务,支持JPA、MongoDB、Neo4j、GemFire和Cassandra。无需手动创建Service和Controller层。要开始,需配置JPA数据源,创建实体类和Repository接口。快速实现REST接口,只需引入spring-boot-starter-data-rest Maven依赖,并在Repository接口上添加@RepositoryRestResource注解。
|
1天前
|
Java 程序员 开发者
深入理解Java并发编程:线程同步与锁机制
【4月更文挑战第30天】 在多线程的世界中,确保数据的一致性和线程间的有效通信是至关重要的。本文将深入探讨Java并发编程中的核心概念——线程同步与锁机制。我们将从基本的synchronized关键字开始,逐步过渡到更复杂的ReentrantLock类,并探讨它们如何帮助我们在多线程环境中保持数据完整性和避免常见的并发问题。文章还将通过示例代码,展示这些同步工具在实际开发中的应用,帮助读者构建对Java并发编程深层次的理解。
|
4天前
|
Java 编译器 开发者
【JAVA】为什么代码会重排序
【JAVA】为什么代码会重排序
|
5天前
|
存储 自然语言处理 Java
【JAVA面试题】什么是代码单元?什么是码点?
【JAVA面试题】什么是代码单元?什么是码点?
|
6天前
|
SQL Java 数据库
java代码中调用dao层查询接口,代码没有返回数据,打印出的sql查出了数据
java代码中调用dao层查询接口,代码没有返回数据,打印出的sql查出了数据
12 1
|
6天前
|
安全 Java 开发者
Java编程:深入探索其原理、特性与实战代码
Java编程:深入探索其原理、特性与实战代码
10 1
|
7天前
|
存储 算法 Java
滚雪球学Java(20):Java泛型与枚举:提升代码灵活性与可读性
【4月更文挑战第9天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
21 1
滚雪球学Java(20):Java泛型与枚举:提升代码灵活性与可读性