- 使用synchronized声明的方法在某些情况下是有弊端的,比如:当A线程调用同步的方法执行一个长时间的任务,那么B线程就需要等待较长的时间才能执行,这样情况下可以使用synchronized代码块去优化代码的执行时间,减小锁的粒度。
- public class Optimize {
- public void doLongTimeTask(){
- try {
- System.out.println("当前线程开始:" + Thread.currentThread().getName() +
- ", 正在执行一个较长时间的业务操作,其内容不需要同步");
- Thread.sleep(2000);
- 同步代码块
- synchronized(this){
- System.out.println("当前线程:" + Thread.currentThread().getName() +
- ", 执行同步代码块,对其同步变量进行操作");
- Thread.sleep(1000);
- }
- System.out.println("当前线程结束:" + Thread.currentThread().getName() +
- ", 执行完毕");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- final Optimize otz = new Optimize();
- Thread t1 = new Thread(new Runnable() {
- @Override
- public void run() {
- otz.doLongTimeTask();
- }
- },"t1");
- Thread t2 = new Thread(new Runnable() {
- @Override
- public void run() {
- otz.doLongTimeTask();
- }
- },"t2");
- t1.start();
- t2.start();
- }
- }
- 输出结果:
- 当前线程开始:t1, 正在执行一个较长时间的业务操作,其内容不需要同步
- 当前线程开始:t2, 正在执行一个较长时间的业务操作,其内容不需要同步
- 当前线程:t2, 执行同步代码块,对其同步变量进行操作
- 当前线程:t1, 执行同步代码块,对其同步变量进行操作
- 当前线程结束:t1, 执行完毕
- 当前线程结束:t2, 执行完毕
- Synchronized可以使用任意Object对象加锁,用法灵活。
- public class ObjectLock {
- public void method1(){
- synchronized (this) { //对象锁
- try {
- System.out.println("do method1..");
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- public void method2(){ //类锁
- synchronized (ObjectLock.class) {
- try {
- System.out.println("do method2..");
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- private Object lock = new Object();
- public void method3(){ //任何对象锁
- synchronized (lock) {
- try {
- System.out.println("do method3..");
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- public static void main(String[] args) {
- final ObjectLock objLock = new ObjectLock();
- Thread t1 = new Thread(new Runnable() {
- @Override
- public void run() {
- objLock.method1();
- }
- });
- Thread t2 = new Thread(new Runnable() {
- @Override
- public void run() {
- objLock.method2();
- }
- });
- Thread t3 = new Thread(new Runnable() {
- @Override
- public void run() {
- objLock.method3();
- }
- });
- t1.start();
- t2.start();
- t3.start();
- }
- }
- 输出结果:
- do method1..
- do method3..
- do method2..
- Synchronized不能使用String的常量池加锁,会出现死循环。
- public class StringLock {
- public void method() {
- // String s = new String("字符串常量")用不会出现死循环
- synchronized ("字符串常量") {
- try {
- while(true){
- System.out.println("当前线程 : " + Thread.currentThread().getName() + "开始");
- Thread.sleep(1000);
- System.out.println("当前线程 : " + Thread.currentThread().getName() + "结束");
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- public static void main(String[] args) {
- final StringLock stringLock = new StringLock();
- Thread t1 = new Thread(new Runnable() {
- @Override
- public void run() {
- stringLock.method();
- }
- },"t1");
- Thread t2 = new Thread(new Runnable() {
- @Override
- public void run() {
- stringLock.method();
- }
- },"t2");
- t1.start();
- t2.start();
- }
- }
- 输出结果:
- 当前线程 : t2开始
- 当前线程 : t2结束
- 当前线程 : t2开始
- 当前线程 : t2结束
- 当前线程 : t2开始
- 当前线程 : t2结束
- 当前线程 : t2开始
- 当前线程 : t2结束
- ……………………
- 死循环。
- 锁对象的改变,当使用一个对象进行加锁的时候,对象本身发生改变,持有的锁就是不同的,如果对象本身不改变,那么依然是同步的,即使对象的属性发生了改变。
- public class ModifyLock {
- private String name ;
- private int age ;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public synchronized void changeAttributte(String name, int age) {
- try {
- System.out.println("当前线程 : " + Thread.currentThread().getName() + " 开始");
- this.setName(name);
- this.setAge(age);
- System.out.println("当前线程 : " + Thread.currentThread().getName() + " 修改对象内容为: "
- + this.getName() + ", " + this.getAge());
- Thread.sleep(2000);
- System.out.println("当前线程 : " + Thread.currentThread().getName() + " 结束");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- final ModifyLock modifyLock = new ModifyLock();
- final ModifyLock modifyLock1 = new ModifyLock();
- Thread t1 = new Thread(new Runnable() {
- @Override
- public void run() {
- modifyLock.changeAttributte("张三", 20);
- }
- },"t1");
- Thread t2 = new Thread(new Runnable() {
- @Override
- public void run() {
- 属性发生了改变
- modifyLock.changeAttributte("李四", 21);
- }
- },"t2");
- t1.start();
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- t2.start();
- }
- }
- 输出结果:结果还是同步的
- 当前线程 : t1 开始
- 当前线程 : t1 修改对象内容为: 张三, 20
- 当前线程 : t1 结束
- 当前线程 : t2 开始
- 当前线程 : t2 修改对象内容为: 李四, 21
- 当前线程 : t2 结束
- 死锁问题,在设计程序时就应该避免双方相互持有对方的锁的情况
- public class DeadLock implements Runnable{
- private String tag;
- private static Object lock1 = new Object();
- private static Object lock2 = new Object();
- public void setTag(String tag){
- this.tag = tag;
- }
- @Override
- public void run() {
- if(tag.equals("a")){
- synchronized (lock1) {
- try {
- System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock1执行");
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- synchronized (lock2) {
- System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock2执行");
- }
- }
- }
- if(tag.equals("b")){
- synchronized (lock2) {
- try {
- System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock2执行");
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- synchronized (lock1) {
- System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock1执行");
- }
- }
- }
- }
- public static void main(String[] args) {
- DeadLock d1 = new DeadLock();
- d1.setTag("a");
- DeadLock d2 = new DeadLock();
- d2.setTag("b");
- Thread t1 = new Thread(d1, "t1");
- Thread t2 = new Thread(d2, "t2");
- t1.start();
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- t2.start();
- }
- }
- 输出结果:
- 当前线程 : t1 进入lock1执行
- 当前线程 : t2 进入lock2执行
5.synchronized代码块。
最新推荐文章于 2024-08-05 16:28:54 发布
