Synchronized学习

Syncronized的作用:

  • 能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果。(有一把锁,持有锁的线程才能执行该段代码)

Syncronized的地位:

  • Synchronized是java的关键字。
  • 是最基本的互斥同步手段。

用法:

  • 对象锁,包括方法锁和同步代码块锁。
  • 类锁,指synchronized修饰静态的方法或指定锁为Class对象。

对象锁

  • 代码块形式要手动指定锁对象
  • 方法锁形式,synchronized修饰普通方法,锁对象默认为this

未加Synchronized关键字:

package syncStu;

public class BlockSyncStu implements Runnable{
    static BlockSyncStu blockSyncStu= new BlockSyncStu();
    @Override
    public void run() {
        System.out.println("我是对象锁的代码块形式。我叫:"+ Thread.currentThread().getName() );
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+" 运行结束" );
    }
    public static void main(String[] args) {
        
        Thread thread1 = new Thread(blockSyncStu,"1111");
        Thread thread2 = new Thread(blockSyncStu,"2222");
        thread1.start();
        thread2.start();
        while ( thread1.isAlive() || thread2.isAlive() ) {}
        System.out.println("finished");
    }
}
/*未加Synchronized关键字 :输出 线程1线程2一起执行run方法*/
我是对象锁的代码块形式。我叫:2222
我是对象锁的代码块形式。我叫:1111
2222 运行结束
1111 运行结束
finished

 加Synchronized代码块:

package syncStu;

public class BlockSyncStu implements Runnable{
    static BlockSyncStu blockSyncStu= new BlockSyncStu();
    @Override
    public void run() {
        synchronized (this) {
            System.out.println("我是对象锁的代码块形式。我叫:"+ Thread.currentThread().getName() );
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" 运行结束" );
        }
    }
    public static void main(String[] args) {
        
        Thread thread1 = new Thread(blockSyncStu,"1111");
        Thread thread2 = new Thread(blockSyncStu,"2222");
        thread1.start();
        thread2.start();
        while ( thread1.isAlive() || thread2.isAlive() ) {}
        System.out.println("finished");
    }
}
我是对象锁的代码块形式。我叫:1111
1111 运行结束
我是对象锁的代码块形式。我叫:2222
2222 运行结束
finished
执行和结束之间都间隔了3S。

 

  •  这里的this锁对象,可以使用Object类型的对象代替,有多个目标块需要竞争同一资源的时候,这几个目标块上的对应参数一致,即可。

Synchronized做方法锁:

package syncStu;

public class MethodStu implements Runnable{
    static BlockSyncStu blockSyncStu= new BlockSyncStu();
    @Override
    public void run() {
        method();
    }
    public synchronized void method() {
        System.out.println("我是对象锁的方法修饰符形式。我叫:"+ Thread.currentThread().getName() );
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+" 运行结束" );
    }
    public static void main(String[] args) {
        Thread thread1 = new Thread(blockSyncStu,"1111");
        Thread thread2 = new Thread(blockSyncStu,"2222");
        thread1.start();
        thread2.start();
        while ( thread1.isAlive() || thread2.isAlive() ) {}
        System.out.println("finished");
    }
    
}
我是对象锁的代码块形式。我叫:1111
1111 运行结束
我是对象锁的代码块形式。我叫:2222
2222 运行结束
finished
这个也是依次执行。 

 

 类锁

概念:

  • java类可能有很多个对象,但是只有一个Class对象。本质上类锁是一个概念,就是同一时刻只能被一个对象拥有。其他对象会被阻塞。

形式:

  • synchronized加在static方法上
  • synchronized(.class)代码块

 

package syncStu;

public class ClassStaticStu implements Runnable{
    //实例1
    static ClassStaticStu blockSyncStu1= new ClassStaticStu();
    //实例2
    static ClassStaticStu blockSyncStu2= new ClassStaticStu();
    @Override
    public void run() {
        method();
    }
    /**
     *     未加了static关键字
     */
    public synchronized void method() {
        System.out.println("我是对象锁的方法修饰符形式。我叫:"+ Thread.currentThread().getName() );
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+" 运行结束" );
    }
    public static void main(String[] args) {
        
        Thread thread1 = new Thread(blockSyncStu1,"1111");
        Thread thread2 = new Thread(blockSyncStu2,"2222");
        thread1.start();
        thread2.start();
        while ( thread1.isAlive() || thread2.isAlive() ) {}
        System.out.println("finished");
    }
}
我是对象锁的方法修饰符形式。我叫:1111
我是对象锁的方法修饰符形式。我叫:2222
2222 运行结束
1111 运行结束
finished
这种是两个实例对应的线程,并没有被synchronized限制,是一起执行的。 

 

 把method()方法变为静态方法:

package syncStu;

public class ClassStaticStu implements Runnable{
    //实例1
    static ClassStaticStu blockSyncStu1= new ClassStaticStu();
    //实例2
    static ClassStaticStu blockSyncStu2= new ClassStaticStu();
    @Override
    public void run() {
        method();
    }
    /**
     *     加了static关键字
     */
    public static synchronized void method() {
        System.out.println("我是对象锁的方法修饰符形式。我叫:"+ Thread.currentThread().getName() );
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+" 运行结束" );
    }
    public static void main(String[] args) {
        
        Thread thread1 = new Thread(blockSyncStu1,"1111");
        Thread thread2 = new Thread(blockSyncStu2,"2222");
        thread1.start();
        thread2.start();
        while ( thread1.isAlive() || thread2.isAlive() ) {}
        System.out.println("finished");
    }
}
我是对象锁的方法修饰符形式。我叫:1111
1111 运行结束
我是对象锁的方法修饰符形式。我叫:2222
2222 运行结束
finished
这种的静态方法上加了synchronized就可以。

 --Java高并发之魂:synchronized深度解析 https://www.imooc.com/learn/1086

  

 

posted @ 2020-09-07 23:10  CodingOneTheWay  阅读(158)  评论(0编辑  收藏  举报
回到顶部