在java多线程编程中,咱们须要对java对象中的资源进行同步管理,确保在同一时刻,只能由同一线程访问类或者对象中的资源,这样能够防止因为几个线程共享同一资源致使不可知的后果。java
方法之一就是利用资源锁(synchronized),废话少说,先上例子编程
例子一多线程
public class S_1 {
public static void main(String[] args) {
for(int i=0;i<5;i++){
new Thread_1().start();
}
}
}ide
class Thread_1 extends Thread{
@Override
public synchronized void run() {
for(int i=0;i<100;i++){
System.out.println(i);
}
}
}this
例子二:线程
public class S_2 {
public static void main(String[] args) {
for(int i=0;i<5;i++){
new Thread_2().start();
}
}
}
class Thread_2 extends Thread{
@Override
public void run(){
synchronized(this){
for(int i=0;i<100;i++){
System.out.println(i);
}
}
}
}
对象
例子三:继承
public class S3 {
public static void main(String[] args) {
for(int i=0;i<5;i++){
new Thread_3().start();
}
}
}
class Thread_3 extends Thread{
public synchronized static void show(){
for(int i=0;i<100;i++){
System.out.println(i);
}
}
@Override
public void run(){
show();
}资源
}
同步
例子四:
public class S_4 {
public static void main(String[] args) {
for(int i=0;i<5;i++){
String lock = "lock";
new Thread_4(lock).start();
}
}
}
class Thread_4 extends Thread{
private String lock ;
public Thread_4(String lock){
this.lock = lock ;
}
@Override
public void run(){
synchronized(lock){
for(int i=0;i<100;i++){
System.out.println(i);
}
}
}
}
以上四个例子是用五个线程从0-99进行打印,他们都是按照前后顺序从0-99进行打印的吗?若是你的答案是按顺序依次打印的话,那你就错了,下边我一一来说解下
例子一,没有按照前后顺序进行打印。咱们对run方法进行了加锁,按理说是该按照前后顺序进行打印的,可是为何结果与咱们想象的不同呢?因为咱们起五个线程的时候,咱们建立了五个Thread_1对象,这样每一个线程都获取了一个对象,每一个线程都获取了本身对象中run方法的锁,因此,这里的资源锁是没有意义的,若是要让这里的锁起做用,除非该Thread_1是单例模式的,这样这些线程都共享一个对象,才会按照前后顺序获取锁
例子二,没有按照前后顺序进行打印。咱们对run方法中的一部分代码进行了synchronized块保护,也应该按照每一个线程依次打印,但为何仍是没有依次打印呢?因为咱们synchronized(this)中的this在五个线程中是没有共享的,五个线程中的this都不同,这样至关于对五个对象进行资源块进行保护,五个线程依然可以同时获取synchronized(this)方法中的代码执行的锁
例子三,按照前后顺序打印。这个例子能够和例子一对应起来看,咱们是在show方法上加的锁,而且show方法是static的,这样这里方法就是类方法,被因此对象共享的,当咱们起五个线程,这五个线程对show方法是共享的,并且该方法被加锁了,当线程来访问的时候,首先看这个方法是否被其余线程使用,若是正在被其余对象使用,对不起,你先等着,等下一个线程用完了,退出了的时候,线程池中轮到你的时候,你才能执行该方法
例子四,按照前后顺序打印。这个例子能够和例子四对应起来看,首先咱们来看下例子4,类Thread_4是一个继承Thread的线程类,他有一个私有变量lock,在其run方法中,咱们用锁块对要打印的语句进行保护,咱们在启动线程的时候,经过构造方法,给Thread_4的lock变量进行赋值,因为咱们启动的五个线程中,每一个Thread对象的lock变量的值都是同一个,即五个线程共享变量lock,因此要执行被synchronized方法锁起来的语句,也必须得到相应的锁才可以执行,对比例子一种,this的值在每一个线程中不同的
最后总结
若是咱们想经过synchronized来修辞方法,来达到在同一时刻,该方法只能被同一线程访问的话,有两个条件
条件一:线程对象是一个单例类
条件二:synchronized修饰的方法是static的
若是咱们想经过synchronized方法来达到在同一时刻,被保护的语句块只能被同一线程访问,其条件是
synchronized方法中传入的对象必须是共享的,即传入的对象必须是同样的
但愿这篇博文对你有用,若是我对synchronized认识不到位的地方,请多多指教