多线程中的synchronized

synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

简单的东西没必要总结,我们来看其中的几个关键点,值得体会,用一个例子说话:

 1 public class Demo4 {
 2     public static void main(String[] args) {
 3         final Output output = new Output();
 4         new Thread(new Runnable() {
 5
 6             @Override
 7             public void run() {
 8                 while(true){
 9                     try {
10                         Thread.sleep(500);
11                     } catch (InterruptedException e) {
12                         e.printStackTrace();
13                     }
14                     output.Output1("chenchi");
15                 }
16             }
17         }).start();
18
19         new Thread(new Runnable() {
20
21             @Override
22             public void run() {
23                 while(true){
24                     try {
25                         Thread.sleep(500);
26                     } catch (InterruptedException e) {
27                         e.printStackTrace();
28                     }
29                     output.Output1("sujunjun");
30                 }
31             }
32         }).start();
33     }
34
35     static class Output {
36         public void Output1(String name) {
37             synchronized (this) {
38                 for (int i = 0; i < name.length(); i++) {
39                     System.out.print(name.charAt(i));
40                 }
41                 System.out.println();
42             }
43         }
44
45         public synchronized void Output2(String name) {
46             for (int i = 0; i < name.length(); i++) {
47                 System.out.print(name.charAt(i));
48             }
49             System.out.println();
50         }
51
52         public synchronized static void Output3(String name) {
53             for (int i = 0; i < name.length(); i++) {
54                 System.out.print(name.charAt(i));
55             }
56             System.out.println();
57         }
58     }
59 }

这个例子很简单,就是同时开启两个线程,声明一个Output内部类的对象,同时访问Output内部类的Output()方法。

1.

output.Output1("chenchi");

output.Output1("sujunjun");

很明显,打印中不会出现数据错误。synchronized ()只要保证括号里面是同一对象就不会产生错误。里面传的是this,由于两者对象都是output,所以加锁成功。

想一下,这样会成功吗?(可以)

     String string = "";
        public void Output1(String name) {
            synchronized (string) {
                for (int i = 0; i < name.length(); i++) {
                    System.out.print(name.charAt(i));
                }
                System.out.println();
            }
        }

这样呢?(可以)

public void Output1(String name) {
            synchronized ("") {
                for (int i = 0; i < name.length(); i++) {
                    System.out.print(name.charAt(i));
                }
                System.out.println();
            }
        }

这样呢?(不可以)

public void Output1(String name) {
            synchronized (name) {
                for (int i = 0; i < name.length(); i++) {
                    System.out.print(name.charAt(i));
                }
                System.out.println();
            }
        }

2.

output.Output1("chenchi");

output.Output2("sujunjun");

很明显,打印中不会出现错误,因为synchronized修饰方法就是相当于给方法加锁的是当前对象。

3.

output.Output1("chenchi");

output.Output3("sujunjun");

很明显,打印会出错。为什么呢?还是因为加锁对象不是同一个了。synchronized修饰静态方法后,上锁对象为当前类对象了。

什么是当前类对象呢?就是Class类型实例,JVM在加载任何一个类时,都会创建一个Class类型的实例描述该类,并且每个类有且只有一个Class的实例描述它。

如何同步?

public void Output1(String name) {
            synchronized (Output.class) {
                for (int i = 0; i < name.length(); i++) {
                    System.out.print(name.charAt(i));
                }
                System.out.println();
            }
        }

这里改了一下Output1方法,Output.class为上锁对象,就保证了同一对象。

时间: 2024-08-06 11:55:00

多线程中的synchronized的相关文章

在一般程序开发中可以使用synchronized同步多线程

假设:有两个boy,都要玩同一个toy,此时就会出现同步情况,必须一个玩好了,另一个才能玩.多线程也是这样子. 如果程序不是高并发的场景,则使用synchronized线程同步足够处理. synchronized关键字解释(synchronized(this)同步代码块也可以被替换为同步对象方法或者同步类方法,本质是一样的): 多个线程,访问同一个对象中的synchronized(this)同步代码块时,每一个线程需要串行得到执行.其他线程必须等待当前线程执行完以后才能执行. 当一个线程对象一个

java中的synchronized关键字

参考:http://www.cnblogs.com/devinzhang/archive/2011/12/14/2287675.html 多线程问题的根因: 多线程环境下,对一个对象更改的时候,一个线程A对某个变量做了改变,但是还没改变完成能,就被另外一个线程B抢去了cpu,那么A就不会再执行了,因此导致了数据不一致行为.针对上面引文中银行取款存款的例子,本来存一百取一百正好抵消,但是由于多线程的之间的肆意抢占,有些取存款的操作没有完成,自然导致结果千奇百怪. 关键点: synchronized

Java多线程4:synchronized锁机制

脏读 一个常见的概念.在多线程中,难免会出现在多个线程中对同一个对象的实例变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实是被更改过的. 多线程线程安全问题示例 看一段代码: public class ThreadDomain13 { private int num = 0; public void addNum(String userName) { try { if ("a".equals(userName)) {

(单例设计模式中)懒汉式与饿汉式在多线程中的不同

/* 目的:分析一下单例设计模式中,懒汉式与饿汉式在多线程中的不同! 开发时我们一般选择饿汉式,因为它简单明了,多线程中不会出现安全问题! 而饿汉式需要我们自己处理程序中存在的安全隐患,但是饿汉式的程序技术含量更高! */ /* class SinglePerson implements Runnable{ private static SinglePerson ss = new SinglePerson("hjz", 22);//恶汉式 private int age; privat

多线程中sleep和wait的区别

前几天去UC笔试,有一道简答题问到了.之前还真一直没留意到这个问题,所以答得也不好. 无论学习什么都好,通过对比学习更有利于发现事物的共性和个性,对于知识点的理解更有明显效果(这也可能是UC笔试题上,5道简答题中,有4道都是关于X与Y的区别的问题的原因之一). 既然自己答得不好,那就写下这篇随笔,来警示下自己(不仅是sleep与wait区别,还有多用这种对比学习的学习方式). 翻了很多资料,说的最多的一句就是, sleep与wait最主要的区别在于,sleep与wait都可以使线程等待,但sle

Java多线程中线程间的通信

一.使用while方式来实现线程之间的通信 package com.ietree.multithread.sync; import java.util.ArrayList; import java.util.List; public class MyList { private volatile static List list = new ArrayList(); public void add() { list.add("apple"); } public int size() {

多线程中的生产者消费者Java源代码(带注释)

同步解决了线程中数据存取不一致的问题,而Object类中的等待与唤醒方法解决了重复存取的问题 以下的生产者消费者Java源代码例子,很好的说明了这一点. 其中包括Info类.Producter类.Consumer类.Test类. <1> Info类如下: 1 package per.producterconsumer; 2 3 public class Info { 4 5 private boolean flag = true; 6 /* 7 * flag=true 表示此时可以生产,但不能

Java多线程中的内存可见性

刚刚看了一下synchronized和volatile的区别,这里做一下笔记. 多线程中内存是如何分配的? 分为主内存和线程内存,当线程与其他线程共享一个变量时,便会把主内存的变量复制到线程内存中去.当发生对变量的修改时,会同步到主内存,主内存再同步到其他线程内存中去. Synchronized实现可见性 JMM对Synchronized规定: 线程加锁时,将清空线程内存中共享变量的值,从而使用共享变量时从主内存中重新读取新值. 线程解锁前,必须把共享变量的最新值刷新到主内存中. 线程执行互斥代

Java多线程中的死锁问题[转]

//申明:本文转载自http://www.cnblogs.com/digdeep/p/4448148.html <Java多线程中的死锁问题> Java程序基本都要涉及到多线程,而在多线程环境中不可避免的要遇到线程死锁的问题.Java不像数据库那么能够检测到死锁,然后进行处理,Java中的死锁问题,只能通过程序员自己写代码时避免引入死锁的可能性来解决. 1. Java中导致死锁的原因 Java中死锁最简单的情况是,一个线程T1持有锁L1并且申请获得锁L2,而另一个线程T2持有锁L2并且申请获得