同步关键词和java线程安全的实例分析
The synchronized code block, the modified code becomes the synchronized block, its role is to call this block of code object, when we use the synchronized keyword, can reduce the scope of the code segment can be reduced as much as possible, in the code segment and synchronization don't add the method of synchronization.This is called Jian Xiaosuo's granularity, making the code more concurrency.
同步方法,修改后的方法成为同步方法,它的作用范围是整个方法,而对象是调用方法的对象。
同步静态方法,修改静态静态方法,其作用范围是整个静态方法,对象是这个类的所有对象。
同步类的一部分同步(className。类)括弧括起来后同步,和行动的对象是这个类的所有对象。
(同步)()在锁定对象,同步(这)是锁定对象本身,同步同一个类的不同对象而不会被锁定,并同步(className。类)实现全局锁功能,所有这个类的对象,调用这个方法有锁定效应,在除了()也可以被添加到一个特定的对象,以达到特定的对象锁。
同步(对象){
在同步代码块中对象的操作
}
同步关键字和线程安全
通过用同步关键字包装代码来同步线程是安全的。测试是错误的。发现是完全错误的。同步必须正确地使用为真正的线程安全。虽然我知道这种写作方式,但我一直认为错误的方法是因为懒惰而使用的。
看来基金会还没有做得很好,还需要检讨和加强!在工作中犯这样的错误是不可原谅的,知道同步关键字在哪里使用很敏感!很多可汗。
首先坚持代码:
com包;
公共课threadtest {
public static void main(String { } args){
必须M1 =新的必须(1);
必须M2 =新的必须(2);
m1.start();
m2.start();
}
}
最终扩展线程类{
私人int Val;
公众必须(int v){
缬氨酸=v;
}
实际上,这种方法不是线程安全的。
公共使用同步print1(int v){
对于(int = i 0;i < 100;i + +){
system.out.print(V);
}
}
公共无效该(int v){
线程安全
同步(必须的。类){
对于(int = i 0;i < 100;i + +){
System.out.print (V);
}
}
}
公共空运行(){
print1(Val);
/ /该(Val);
}
}
对于懒惰和出汗的缘故。程序员总是懒。写不写不写。我必须为一个匿名内部类,最后,以方便调用。它采用最直接继承Thread类实现线程,定义运行()方法需要运行。
首先,该()方法的注释看print1结果are.print1()()是一个使用synchronized关键字的定义方法,我一直认为这也可以实现线程安全。我不知道,我错了。
让我们直接运行主()方法。控制台打印结果如下所示:
复制代码代码如下所示:
1212111121212121212121212121212121212121222222212121212。
这是一系列1和2交叉打印的结果。在我的主要方法中,我先运行M1,然后运行M2,没有线程同步!
必须M1 =新的必须(1);
必须M2 =新的必须(2);
m1.start();
m2.start();
然后我们print1(注释)的运行方法,运行该();
控制台打印如下:
复制代码代码如下所示:
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
线程确实是安全的。人们认为这也是众所周知的。然而,由于它的小代码,它没有考虑太多。似乎有时是好的懒惰。重要的是要打好基础。一个错误已经纠正了很长一段时间。
现在我们来看看具体的原因。
同步关键字可以用作函数的修饰符,也可以用作函数中的语句,也就是常用的同步方法和同步块。如果我们对它进行更精细的分类,同步可以作用于实例变量、对象引用(对象引用)、静态函数和类字面值(类名常量)。
在进一步阐述之前,我们需要明确几个要点:
在方法或对象中添加同步关键字,它获得的锁是对象,而不是一段代码或函数作为锁,而同步方法很可能被其他线程访问。
b.每个对象只有一个锁(锁)与它相关联。
C.同步是大量系统开销的代价,甚至是死锁的可能原因,因此可以避免不必要的同步控制。
然后讨论同步使用不同位置对代码的影响:
假设P1和P2是同一类的不同对象,在下列情况下定义同步块或同步方法,可以由P1和P2调用。
1。当同步用作函数修饰符时,示例代码如下所示:
公共使用同步methodaaa()
{
/…
}
这是同步方法,然后哪个对象是同步锁定的它的锁是调用同步方法对象,也就是说,当对象P1在不同线程中执行同步方法时,它们形成互斥来实现同步效果,但是这个对象类产生的另一个对象P2可以随意调用附加的同步关键字的方法。
上面的示例代码相当于下面的代码:
公共无效methodaaa()
{
同步(此)(1)
{
/…
}
}
(1)这指的是什么它是指调用该方法的对象,如P1,可见同步的本质是同步使用对象引用,即获得P1对象锁的线程可以调用P1的同步方法。对于P2,P1锁与它无关。在这种情况下,程序也可以摆脱同步机制,造成数据混乱。
2。同步块,示例代码如下所示:
public void方法(someobject所以)
{
同步(SO)
{
/…
}
}
此时,锁是这样的对象,谁得到了锁,谁可以运行它所控制的代码,当一个清除对象用作锁时,它就可以编写像这样的程序,但是当没有显式对象作为锁时,只需要同步代码,就可以创建一个特殊的实例变量,这是一个充当锁的对象。
实现了Runnable接口的类Foo
{
私有字节{锁} =新字节{ 0 };特殊实例变量
public void方法()
{
同步(锁定)…
}
/…
}
注意:零长度字节数组对象将比任何对象都更经济——查看编译后的字节码:生成零长度字节{对象}只需要3个操作码,而对象锁定=新对象()需要7行操作码。
三.同步应用于静态函数,示例代码如下所示:
类Foo
{
公共同步静态(methodaaa) / /静态同步功能
{
/…
}
公共无效methodbbb()
{
同步(富类)类文字(类文字)
}
}
在代码(methodbbb)方法是类的文字作为一个锁,它的静态功能和同步的效果是相同的,锁很特别,是调用的方法属于类的对象(类,而不是一个特定的对象类。生成)。
记得在有效的java,是用foo.class和p1.getclass不同()作为同步锁。p1.getclass不能用来锁class.p1指由Foo类生成的对象。
我们可以推断:如果一个类定义了一个静态函数同步,例如B也定义了一个同步的功能,然后在多线程访问A和B分别,两种方法的类对象相同的对象,不构成锁同步,因为它们是不一样的一种方法。锁是obj的对象,和B锁类obj属于。
摘要如下:
找出同步锁定的对象可以帮助我们设计一个更安全的多线程程序。
还有其他技术使我们能够更安全地同步访问共享资源:
1。界定民营+得到方法的实例变量,而不是定义的公共/ protected.if变量实例变量被定义为公共的,对象可以直接从外同步方法的控制和改变它,这也是一个JavaBean的标准实现。
2。如果实例变量是一个对象,如数组或数组的东西,认为上述方法仍然是不安全的,因为当外部对象的引用通过get方法获取实例对象,它指向另一个对象,然后改变私有变量,这是非常危险的。此时,我们需要同步的方法和同步获得,只有返回克隆()的私有对象,调用获取对象的复制参考。
总结一些同步音符:
当两个并发线程访问同一对象的同步块时,只能同时执行一个线程。另一个线程被阻塞,代码块必须等待,直到当前线程执行块。这两个线程是互斥的,因为在执行同步代码块时,当前对象将被锁定。只有在执行块之后,对象锁才能被释放,下一个线程才能执行并锁定对象。
当线程访问对象的同步(同步)块时,另一个线程仍然可以访问对象中的非同步(这个)同步块(两个线程使用相同的对象)。
当线程访问对象的同步(同步)块时,其他线程将阻塞对象中的所有其他同步(此)同步代码块。(同一时间,两个线程使用同一个对象)。