内部锁synchronized基本使用

news/2024/5/17 18:15:33 标签: synchronized, 多线程, 锁的可重入性

synchronized_0">synchronized基本使用

对于线程来说,如果多个线程只是相互间单独执行的话,本身是没有太大意义的,一般来说,都是需要多个线程,相互间协作来进行工作的,这样使用,才会对系统带来实际的意义。
​ 在Java中支持多个线程同时访问一个对象或对象中的成员变量,但是如果没有任何保护机制的话,就会出现数据不一致的情况,效果如下:

public class TestThread {
    public static void main(String[] args) {
        TestThread testThread = new TestThread();
        new Thread(new Runnable() {
            @Override
            public void run() {
                testThread.print();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                testThread.print();
            }
        }).start();
    }
    public void print(){
        for(int i=0;i<1000;i++){
            System.out.println(Thread.currentThread().getName()+"--->"+i);
        }
    }
}

在这里插入图片描述

现在要解决这个问题的话,就可以使用锁来进行解决。synchronized可以修饰方法或者以同步块的形式来进行使用,它主要确保多个线程在同一个时刻,只能有一个线程处于方法或者同步块中,它保证了线程对变量访问的可见性和排他性,又称为内置锁机制。

对象锁

在同步代码块(或者同步方法)中拥有同一个对象锁的线程,如果有一个线程获得了锁,其他线程只能等该线程释放锁后才可以获得锁。

this锁对象

public class TestThread {
    public static void main(String[] args) {
        TestThread testThread = new TestThread();
        new Thread(new Runnable() {
            @Override
            public void run() {
                testThread.print();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                testThread.print();
            }
        }).start();
    }
    //同步代码块
    public void print(){
        synchronized (this){
            for(int i=0;i<1000;i++){
                System.out.println(Thread.currentThread().getName()+"--->"+i);
            }
        }
    }
         //同步方法,synchronized 默认this作为锁对象
         /* public synchronized void print(){
            for(int i=0;i<1000;i++){
                System.out.println(Thread.currentThread().getName()+"--->"+i);
            }
    }*/
}

在这里插入图片描述

常量锁对象

public class TestThread {
    public static void main(String[] args) {
        TestThread testThread = new TestThread();
        new Thread(new Runnable() {
            @Override
            public void run() {
                testThread.print();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                testThread.print();
            }
        }).start();
        //调用静态方法
        new Thread(new Runnable() {
            @Override
            public void run() {
                TestThread.print2();
            }
        }).start();
    }
    private static final Object obj = new Object();
    public void print(){
        synchronized (obj){
            for(int i=0;i<1000;i++){
                System.out.println(Thread.currentThread().getName()+"--->"+i);
            }
        }

    }
    
    public static void print2(){
        synchronized (obj){
            for(int i=0;i<1000;i++){
      System.out.println(Thread.currentThread().getName()+"--->"+i);
            }
        }
    }
}

类锁

synchronized修饰静态方法时把运行时类作为锁


public class TestThread {
    public static void main(String[] args) {
        TestThread testThread = new TestThread();
        new Thread(new Runnable() {
            @Override
            public void run() {
                testThread.print();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                testThread.print2();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                TestThread.print2();
            }
        }).start();
    }
    //将TestThread的字节码文件作为锁对象
    public synchronized void print(){
        synchronized (TestThread.class){
            for(int i=0;i<1000;i++){
                System.out.println(Thread.currentThread().getName()+"--->"+i);
            }
        }

    }
    //synchronized修饰静态方法 
    public static synchronized void print2(){
            for(int i=0;i<1000;i++){
             System.out.println(Thread.currentThread().getName()+"--->"+i);
            }
    }
}

以上三种方式都是将TestThread 的字节码文件作为锁对象,因此也可以实现同步

锁的可重入性

如果当前线程已经拥有锁对象,可以再次重复获得同一锁对象而不会出现死锁问题。

public class Reentrant {

    public synchronized void function1(){
        System.out.println("同步方法1");
        function2();
    }
    public synchronized void function2(){
        System.out.println("同步方法2");
        function3();
    }
    public synchronized void function3(){
        System.out.println("同步方法3");
    }

    public static void main(String[] args) {
        Reentrant reentrant = new Reentrant();
        new Thread(new Runnable() {
            @Override
            public void run() {
                reentrant.function1();
            }
        }).start();
    }
}

http://www.niftyadmin.cn/n/1597903.html

相关文章

《Oracle编程艺术》学习笔记(38)-表分区

分区&#xff08;partitioning&#xff09;在Oracle 8.0中引入&#xff0c;将一个表或索引物理地分解为多个更小、更可管理的部分。 11g之前有4种对表分区的方法&#xff1a; 1&#xff09;区间分区&#xff1a;指定数据区间来决定数据存储在哪个分区。 2&#xff09;散列分区&…

《Oracle编程艺术》学习笔记(39)-索引分区

对索引进行分区有两种方法&#xff1a;1) 随表对索引完成相应的分区&#xff1a;这也称为局部分区索引&#xff08;locally partitioned index&#xff09;。每个表分区都有一个索引分区&#xff0c;而且只索引该表分区。一个给定索引分区中的所有条目都指向一个表分区&#xf…

显示锁Lock基本操作

显示锁Lock基本操作 ReentrantLock可重入锁 import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;public class LockThread extends Thread{private Lock lock;private static int num0;public LockThread(Lock lock) {this.locklock…

多线程代码演示

多线程代码演示 wait/notify演示 /*** 演示wait()/notify()*/ public class WaitAndNotifyTest {public static void main(String[] args) {Object obj new Object();new Thread(new Runnable() {Overridepublic void run() {synchronized (obj){try {System.out.println(&qu…

Spring中Aspectj和Schema-based AOP混用引起的错误

前几天要在项目中增加一个新功能用来监控某些模块的运行情况&#xff0c;自然就想到了使用Spring的AOP来实现。之前已经有类似的AOP代码&#xff0c;使用的是Schema-based形式配置的&#xff0c;也就是在Spring的ApplicationContext.xml中加入了&#xff1a; <bean id"…

spring注解@Autowired和@Resource

Autowired和Resource的区别 测试准备 创建Student 类、School类、PrimarySchool类并对基本数据类型采用注解方式进行赋值 //Student引用school public class Student {private School school;Value("张三")private String sname;Value("22")private int…

《Oracle编程艺术》学习笔记(40)-分区的优点

1&#xff09;提高数据的可用性在一个大对象中如果一个分区不可用&#xff0c;查询可以消除这个分区而不予考虑。 恢复数据也可以更快。现在恢复的时间就只是恢复一个分区所需的时间。 例如下面把把2010年数据的分区离线&#xff0c;使这个分区不可用&#xff0c;可以通过在查…

解决阿里云Tomcat8080端口拒绝访问

解决阿里云Tomcat8080端口拒绝访问