首先,需要说明一点,也是最重要的一点,无论是同步方法 还是 同步块 都是只针对同一个对象的多线程而言的,只有同一个对象产生的多线程,才会考虑到 同步方法 或者是 同步块,如果定义多个实例的同步,可以考虑使用mutex,创建类似于c++整个服务全局锁,或者创建一个全局单例类,在其内定义全局锁。比如以下的代码片段定义线程同步无任何意义:
public class Test1 implements Runnable {
public void run() {
synchronized(this) {
try {
System.out.println(System.currentTimeMillis());
Thread.sleep(2000);
System.out.println(System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
for(int i=0;i<10;i++) {
new Thread(new Test1()).start(); // 关键,如果将 new Test1拿到外面,那么同步方法才有意义,如下:
//public static void main(String[] args) {
// Test1 test=new Test1();
// for(int i=0;i<10;i++) {
// new Thread(test).start();
}
}
}
因为java或者C#中的线程同步与多线程的概念,只是在单个对象下 这一范围内的,也就是说:单个对象下的 多线程同步 或者 死锁。如果有下面的需求:
1,该类只允许在同一时刻实例化(new)一次;----考虑单例模式
2,或者只允许在同一时刻仅可存活一个对于数据库的修改 或 删除操作;--考虑单例模式 或者 数据库内的事务锁概念。
-----------------------------------------------------
下面我们着重介绍java中的 Sychronized的用法,具体为:同步方法 与 同步块
synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。
1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:
public synchronized void accessVal(int newVal);
synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。
synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为 synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供了更好的解决办法,那就是 synchronized 块。
2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:
synchronized(syncObject) {
//允许访问控制的代码
}
synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。
对synchronized(this)的一些理解
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用
------------------------------------------------------------------------
网上还有很多关于java中的Sychronized的个人理解与总结,可以忘记的时候看看,但是上面的东东是核心,切记。
此外最关键的,线程同步会耗费很多性能,所以如无必要,尽量少用线程同步,如果使用最好使用同步块而不要使用同步方法。
分享到:
相关推荐
同步代码块和同步方法是Java中确保线程安全的重要机制。它们各有优缺点,适用于不同的场景。在实际开发中,开发者应该根据具体需求选择合适的同步机制。通过合理使用同步代码块和同步方法,可以有效地控制线程对共享...
在Java中,同步是通过`synchronized`关键字实现的,它用于确保同一时间只有一个线程可以执行特定代码块。这有助于维护数据的完整性,特别是在多个线程可能同时修改同一对象的情况下。 1. 静态方法同步: 静态方法是...
本篇将详细解释如何使用Java多线程来实现火车售票系统,并探讨Java中同步的实现,包括同步块(synchronized block)和同步方法(synchronized method)。 首先,火车售票系统的模拟通常是为了演示线程间的协作和...
同步方法和同步代码块是Java中实现同步的主要方式,它们都用于解决线程安全问题,但有各自的特点和适用场景。 同步方法是通过在方法声明前加上`synchronized`关键字来实现的。例如: ```java public synchronized ...
本篇文章将详细介绍`synchronized`的两种形式:同步代码块和同步方法,并分析它们的区别。 1. **同步代码块 (Synchronized Block)** 同步代码块的语法结构如下: ```java synchronized (object) { // 需要同步...
例如,清单2中将同步代码块外移,先进行线程安全的预处理,然后在同步块内仅执行关键操作,如从HashMap中获取值。 2. **使用并发工具**:Java提供了一些并发工具类,如`java.util.concurrent`包中的`Atomic`类、`...
本篇文章将深入探讨Java同步代码块和同步方法的原理及其在实际应用中的案例,以实现一个简单的买票系统为例。 首先,我们需要理解“原子性”这个概念。在多线程环境中,原子性意味着一段代码在执行过程中不会被其他...
本教程将深入讲解Java中的多线程以及同步控制机制,特别是同步代码块和同步方法。 首先,我们要理解什么是线程。线程是程序执行的最小单位,一个进程中可以有多个线程并发执行。在Java中,可以通过实现`Runnable`...
Java提供了多种机制来实现线程同步,主要包括synchronized关键字、wait()、notify()和notifyAll()方法以及ReentrantLock等。 1. **synchronized关键字**:这是Java中最基本的线程同步方式。它可以用于修饰方法或...
本例程主要关注的是libusb中的“块传输”和“同步传输”功能,这两种传输模式是USB通信中不可或缺的部分。下面我们将深入探讨这两个概念以及如何在libusb中实现它们。 首先,USB块传输(Bulk Transfer)是USB协议中...
本文将深入探讨几种异步时钟域同步化处理的方法,以确保系统稳定性和可靠性。 首先,我们来理解一下什么是异步时钟域。在FPGA设计中,不同的模块或功能块可能由不同的时钟源驱动,这些时钟源的频率可能相同也可能...
在这个例子中,`increment()`和`decrement()`方法都用到了同步代码块,使得计数操作不会因线程并发而出现不正确的结果。 通过这两个示例,我们可以学习到同步代码块在实际编程中的应用,以及如何解决多线程环境下的...
Monitor类提供了Enter和Exit方法来获取和释放对象锁,确保同一时间只有一个线程能访问受保护的代码块,即临界区。与lock语句类似,但Monitor提供更多的灵活性,如TryEnter尝试获取锁、Wait使当前线程等待、Pulse和...
在具体的方法和装置设计中,电信设备可能会采用各种策略来优化广播同步和RMSI的传输。例如,设备可能利用特定的同步信号或参考信号来实现精确的定时同步。此外,可能采用高效的编码和调制技术来增强广播信息的抗干扰...
4. **wait()、notify()和notifyAll()**:这些是Object类的方法,可以在同步块中使用,用于线程间的通信。`wait()`会让当前线程等待,`notify()`或`notifyAll()`会唤醒等待的线程。 5. **volatile关键字**:虽然不是...
在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。
当线程通过`synchronized`关键字进入同步代码块或同步方法时,它会获取对象的锁。如果锁已被其他线程持有,那么该线程将会被阻塞,直到锁被释放。锁的状态存储在对象头的Mark Word中,包括线程ID等信息。 三、同步...
在RAID5中,同步和异步主要涉及数据的写入过程。同步(Synchronous)写意味着在数据写入所有相关的磁盘后,系统才会确认该写操作完成。这种模式提供了更高的数据安全性,因为即使在写入过程中发生故障,其他磁盘上的...
6. **全量与增量切换**:DataX 允许你在同一份配置中灵活切换全量和增量同步。只需修改配置文件中的增量条件或移除条件即可实现。 值得注意的是,DataX 的可配置性非常强,它允许用户自定义 Reader 和 Writer,扩展...