多线程学习总结----synchronized
之前写过一篇多线程学习总结(一),基础的都介绍过了。这次主要讲解一下多线程并发处理的关键字synchronized~
一、什么是synchronized
简单的来讲,synchronized同步锁就是用来解决共享资源竞争的问题。
实现思路:
1.先把共享的执行资源用synchronized包裹,并传递一个共享对象作为synchronized同步锁的钥匙。
2.只有获取到这个共享对象钥匙的线程,才可以获取执行synchronized包裹的内容。
3.没有获取到的线程,进入阻塞,等待锁资源释放。
二、什么实例锁和全局锁
实例锁:锁在某个实例对象上。如果该类是单例,那么该锁也是具有全局锁的概念。实例锁对应的就是synchronized关键字。
全局锁:该锁针对的是类,无论实例多少个对象,那么线程都共享该锁。全局锁对应的就是static synchronized(或者是锁在该类的class或者classloader对象上)。
三、
synchronized使用
具体应用方式有以下三种:
1. public void synchronized XXX(){} 2. synchronized(this){} 3. public static void synchronized XXX(){}
区别:
方式1和2锁的都是当前执行体所在的对象,属于实例锁. synchronized方法是用synchronized修饰方法,这是一种粗粒度锁;
synchronized代码块是用synchronized修饰代码块,这是一种细粒度锁。
一般情况下,细颗粒度锁速度要高于粗颗粒度
而方式3由于加了static,锁的就是当前类对象.属于全局锁(注意,java中类对象只有一个,而对象是有类对象实例化产生的,会有多个)
下面演示synchronized的使用
代码一: package com.my.thread; public class ThreadDemo implements Runnable{ @Override public void run() { synchronized(this){ for(int i=0;i<5;i++){ try { Thread.sleep(100); System.out.println(Thread.currentThread().getName()+" loop "+i); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { Runnable threadDemo = new ThreadDemo(); new Thread(threadDemo,"t1").start(); new Thread(threadDemo,"t2").start(); } } 结果: 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 代码二: package com.my.thread; public class ThreadDemo implements Runnable{ @Override public void run() { synchronized(this){ for(int i=0;i<5;i++){ try { Thread.sleep(100); System.out.println(Thread.currentThread().getName()+" loop "+i); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { new Thread(new ThreadDemo(),"t1").start(); new Thread(new ThreadDemo(),"t2").start(); } } 结果: t2 loop 0 t1 loop 0 t2 loop 1 t1 loop 1 t1 loop 2 t2 loop 2 t2 loop 3 t1 loop 3 t1 loop 4 t2 loop 4
两段代码,我们可以看出来synchronized(this) 这个锁的this是指的当前执行体所在的对象。
而代码一中,可以看到锁的this是同一个对象,所以线程一和线程二互斥执行的。而代码二中,由于锁的对象并非同一个对象,所以执行起来并无影响。
再看一下方式3的使用
代码: package com.my.thread; public class ThreadDemo1 { static class Demos { public static synchronized void isSyncA(){ for(int i=0;i<5;i++){ try { Thread.sleep(100); System.out.println(Thread.currentThread().getName()+" say "+i); } catch (InterruptedException e) { e.printStackTrace(); } } } } Demos demos1 = new Demos(); Demos demos2 = new Demos(); public void deal(){ Thread t1 = new Thread(new Runnable(){ @Override public void run() { demos1.isSyncA(); } },"t1"); Thread t2 = new Thread(new Runnable(){ @Override public void run() { demos2.isSyncA(); } },"t2"); t1.start(); t2.start(); } public static void main(String[] args) { ThreadDemo1 threadDemo1 = new ThreadDemo1(); threadDemo1.deal(); } } 结果: t2 say 0 t2 say 1 t2 say 2 t2 say 3 t2 say 4 t1 say 0 t1 say 1 t1 say 2 t1 say 3 t1 say 4
从上面可以看出来,static synchronized是锁的当前类对象,和创建的对象无关。所以最后结果也显示了出,线程之间执行公共代码产生互斥。
本次就到此为之了,多线程的学习我也才刚刚开始,希望日后多学习多总结多分享了~~~