(a == 1 && a == 2 && a == 3) สามารถประเมินเป็นจริงใน Java ได้หรือไม่


176

เรารู้ว่ามันสามารถใน JavaScript

แต่เป็นไปได้ไหมที่จะพิมพ์ข้อความ "Success" ตามเงื่อนไขที่ระบุด้านล่างใน Java?

if (a==1 && a==2 && a==3) {
    System.out.println("Success");
}

มีคนแนะนำ:

int _a = 1;
int a  = 2;
int a_ = 3;
if (_a == 1 && a == 2 && a_ == 3) {
    System.out.println("Success");
}

แต่ด้วยการทำเช่นนี้เรากำลังเปลี่ยนตัวแปรจริง มีวิธีอื่น ๆ ?


5
&&เป็นandตัวดำเนินการเชิงตรรกะซึ่งหมายความว่าaควรมีค่า 1, 2 และ 3 ในเวลาเดียวกันซึ่งเป็นไปไม่ได้ในเชิงตรรกะ คำตอบคือไม่เป็นไปไม่ได้ คุณต้องการเขียนifคำสั่งที่ตรวจสอบว่าaมีหนึ่งในค่า 1, 2 หรือ 3 หรือไม่?
Boris Pavlović

16
หมายเหตุสำหรับทุกคน: คำถามนี้อาจมาจากคำถามเดียวกันสำหรับ Javascript: stackoverflow.com/questions/48270127/…ซึ่งในกรณีนี้คำตอบคือyes
nos

28
@ArthurAttout ไม่ใช่คำถามที่ซ้ำกันคำถามนั้นมีไว้สำหรับ Javascript ไม่ใช่ Java
เลขที่

13
ส่วนที่ใช้ช่องว่างในชื่อตัวแปรนั้นใช้งานได้ใน Java เช่นกัน แต่แน่นอนว่านี่เป็นแบบเดียวกับที่ใช้_ยกเว้นคุณจะมองไม่เห็น
tobias_k

8
@Seelenvirtuose True แต่if(a==1 && a==2 && a==3)ไม่จำเป็นต้องประเมินพร้อมกัน และนั่นสามารถใช้ในการทำให้งานนี้โดยไม่ต้องหันไปใช้เทคนิค Unicode
Erwin Bolwidt

คำตอบ:


325

ใช่มันค่อนข้างง่ายที่จะทำสิ่งนี้ด้วยหลาย ๆ เธรดถ้าคุณประกาศว่าตัวแปรเปลี่ยนแปลงได้aง่าย

ด้ายหนึ่งเปลี่ยนแปลงอย่างต่อเนื่องตัวแปร 1-3 a == 1 && a == 2 && a == 3และหัวข้ออื่นอย่างต่อเนื่องทดสอบว่า มันเกิดขึ้นบ่อยครั้งพอที่จะพิมพ์ "ความสำเร็จ" ต่อเนื่องบนคอนโซล

(หมายเหตุหากคุณเพิ่มส่วนelse {System.out.println("Failure");}คำสั่งคุณจะเห็นว่าการทดสอบล้มเหลวบ่อยกว่าที่ทำสำเร็จ)

ในทางปฏิบัติมันยังทำงานได้โดยไม่ต้องประกาศaว่ามีความผันผวน แต่มีเพียง 21 ครั้งใน MacBook ของฉัน โดยไม่ต้องvolatileคอมไพเลอร์หรือ HotSpot ได้รับอนุญาตให้แคชaหรือเปลี่ยนคำสั่งด้วยif if (false)เป็นไปได้มากว่าฮอตสปอตจะเริ่มทำงานหลังจากนั้นครู่หนึ่งและคอมไพล์มันให้กับคำแนะนำการประกอบที่ทำแคชค่าaไว้ ด้วย volatileมันจะพิมพ์ "ความสำเร็จ" ตลอดไป

public class VolatileRace {
    private volatile int a;

    public void start() {
        new Thread(this::test).start();
        new Thread(this::change).start();
    }

    public void test() {
        while (true) {
            if (a == 1 && a == 2 && a == 3) {
                System.out.println("Success");
            }
        }
    }

    public void change() {
        while (true) {
            for (int i = 1; i < 4; i++) {
                a = i;
            }
        }
    }

    public static void main(String[] args) {
        new VolatileRace().start();
    }
}

83
นี่เป็นตัวอย่างที่ยอดเยี่ยม! ฉันคิดว่าฉันจะขโมยมันในครั้งต่อไปที่ฉันกำลังพูดถึงปัญหาการเห็นพ้องด้วยกันที่อาจเป็นอันตรายกับผู้พัฒนารุ่นเยาว์ :)
อเล็กซ์ปรัสเซีย

6
มันไม่ได้มีโอกาสมากโดยไม่ต้องvolatileแต่ในหลักการนี้ยังสามารถเกิดขึ้นได้โดยไม่ต้องใช้คำสำคัญและมันจะเกิดขึ้นจำนวนข้อของครั้งในขณะที่ในมือที่มีการรับประกันว่ามันเคยจะไม่เกิดขึ้นแม้จะมีvolatile volatileแต่แน่นอนว่าการที่มันเกิดขึ้นในทางปฏิบัตินั้นเป็นเรื่องที่น่าประทับใจและเงียบสงบ ...
Holger

5
@ AlexPruss ฉันเพิ่งทำ devs ทั้งหมดไม่ใช่แค่รุ่นน้องใน บริษัท ของฉัน (ฉันรู้ว่ามันเป็นไปได้) 87% ประสบความสำเร็จจากความล้มเหลวในการตอบคำถาม
Eugene

3
@ Holger True ไม่มีการรับประกันใด ๆ ในสถาปัตยกรรมแบบ multi-full-core ทั่วไปหรือ multi-cpu โดยที่ทั้งสองเธรดได้รับการกำหนดให้กับคอร์ที่แยกกันก็มีแนวโน้มที่จะเกิดขึ้นvolatileได้ อุปสรรคหน่วยความจำที่สร้างขึ้นเพื่อvolatileทำให้เธรดช้าลงและทำให้มีโอกาสมากขึ้นที่จะดำเนินการซิงค์ในช่วงเวลาสั้น ๆ มันเกิดขึ้นบ่อยกว่าที่ฉันคาดไว้ มันมากระยะเวลาที่มีความอ่อนไหว แต่ฉันเห็นประมาณว่าระหว่าง 0.2% และ 0.8% ของการประเมินผลของการกลับมา(a == 1 && a == 2 && a == 3) true
Erwin Bolwidt

4
นี่เป็นคำตอบเดียวที่ทำให้โค้ดที่ต้องการส่งคืนจริงแทนที่จะสร้างรูปแบบขนาดเล็กที่เหมือนกัน +1
Alejandro

85

ใช้แนวความคิด (และรหัส) จากรหัสคำตอบกอล์ฟยอดเยี่ยม , Integerค่าสามารถสับสนกับ

ในกรณีนี้มันสามารถทำให้ints casted Integerเท่ากับเมื่อพวกเขาไม่ปกติ:

import java.lang.reflect.Field;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        Class cache = Integer.class.getDeclaredClasses()[0];
        Field c = cache.getDeclaredField("cache");
        c.setAccessible(true);
        Integer[] array = (Integer[]) c.get(cache);
        // array[129] is 1
        array[130] = array[129]; // Set 2 to be 1
        array[131] = array[129]; // Set 3 to be 1

        Integer a = 1;
        if(a == (Integer)1 && a == (Integer)2 && a == (Integer)3)
            System.out.println("Success");
    }
}

น่าเสียดายที่มันไม่ได้สวยหรูเท่าคำตอบแบบมัลติเธรดของ Erwin Bolwidt (เหมือนกับอันนี้ต้องใช้Integerการคัดเลือก)แต่ก็ยังมีบางคนที่สนุกเสฉวนเกิดขึ้น


น่าสนใจมาก. ฉันถูก toying Integerกับการเหยียดหยาม มันเป็นเรื่องน่าอายเกี่ยวกับการคัดเลือกนักแสดง แต่ก็ยังเจ๋ง
ไมเคิล

@Michael ฉันไม่สามารถหาวิธีกำจัดการคัดเลือกได้ aการถูกตั้งค่าเป็น 1/2/3 จะทำให้คุณพึงพอใจa == 1แต่มันจะไม่ไปในทาง
ตรงกันข้าม

4
ฉันตอบคำถามนี้ไม่กี่วันที่ผ่านมาใน JS / ทับทิม / Javaงูใหญ่และ รุ่นที่น่าเกลียดอย่างน้อยผมสามารถหาได้ที่จะใช้a.equals(1) && a.equals(2) && a.equals(3)ซึ่งกองกำลัง1, 2และ3จะได้รับการ autoboxed เป็นIntegers
Eric Duminil

@EricDuminil นั่นอาจทำให้ความสนุกออกมาเพราะถ้าคุณทำaชั้นเรียนด้วยboolean equals(int i){return true;}ล่ะ
phflack

1
อย่างที่ฉันบอกไปมันน้อยน่าเกลียด แต่ก็ยังไม่เหมาะ ด้วยInteger a = 1;ในบรรทัดก่อนก็ยังคงชัดเจนaจริงๆเป็นจำนวนเต็ม
Eric Duminil

52

ในคำถามนี้ @aioobe แนะนำ (และแนะนำต่อต้าน) การใช้ตัวประมวลผลล่วงหน้า C สำหรับคลาส Java

แม้ว่าจะมีการโกงอย่างมากแต่นั่นก็เป็นทางออกของฉัน:

#define a evil++

public class Main {
    public static void main(String[] args) {
        int evil = 1;
        if (a==1 && a==2 && a==3)
            System.out.println("Success");
    }
}

หากดำเนินการโดยใช้คำสั่งต่อไปนี้มันจะออกตรงหนึ่งSuccess :

cpp -P src/Main.java Main.java && javac Main.java && java Main

6
ความรู้สึกแบบนี้เรียกใช้รหัสผ่านการค้นหาและแทนที่ก่อนที่จะรวบรวมจริง ๆ แต่ฉันสามารถเห็นบางคนที่ทำอะไรแบบนั้นเป็นส่วนหนึ่งของเวิร์กโฟลว์ของพวกเขา
phflack

1
@phackack ฉันชอบเนื้อหาคำถามนี้เกี่ยวกับการแสดงอันตรายของการตั้งสมมติฐานเมื่ออ่านรหัส มันง่ายที่จะสันนิษฐานว่าaเป็นตัวแปร แต่อาจเป็นโค้ดใดก็ได้ในภาษาที่มีตัวประมวลผลล่วงหน้า
วิน

2
ไม่ใช่จาวา เป็นภาษา "Java หลังจากผ่าน C preprocessor" ช่องโหว่ที่คล้ายกันโดยใช้นี้คำตอบ (หมายเหตุ: underhandedอยู่นอกหัวข้อสำหรับ Code Golf ตอนนี้)
user202729

40

เนื่องจากเรารู้แล้วว่าเป็นไปได้ที่จะทำให้โค้ดนี้ประเมินเป็นจริงขอบคุณคำตอบที่ยอดเยี่ยมของErwin Bolwidtและphflackฉันต้องการแสดงให้เห็นว่าคุณต้องให้ความสนใจในระดับสูงเมื่อจัดการกับเงื่อนไขที่ดูเหมือนว่านำเสนอ ในคำถามบางครั้งสิ่งที่คุณเห็นอาจไม่ตรงกับที่คุณคิด

นี่คือความพยายามของฉันเพื่อแสดงว่ารหัสนี้พิมพ์Success!ไปที่คอนโซล ฉันรู้ว่าฉันโกงนิดหน่อยแต่ฉันก็ยังคิดว่านี่เป็นสถานที่ที่ดีในการนำเสนอที่นี่

ไม่ว่าจุดประสงค์ในการเขียนโค้ดเช่นนี้จะเป็นอย่างไร - ดีกว่าที่จะทราบวิธีจัดการกับสถานการณ์ต่อไปนี้และวิธีการตรวจสอบว่าคุณไม่ผิดกับสิ่งที่คุณคิดว่าคุณเห็น

ฉันใช้ Cyrillic 'a' ซึ่งเป็นตัวละครที่แตกต่างจากละติน 'a' คุณสามารถตรวจสอบตัวอักษรที่ใช้ในงบถ้าที่นี่

สิ่งนี้ใช้งานได้เพราะชื่อของตัวแปรนั้นมาจากตัวอักษรที่แตกต่างกัน พวกมันคือตัวบ่งชี้ที่แตกต่างสร้างตัวแปรที่แตกต่างกันสองตัวที่มีค่าต่างกันในแต่ละตัว

โปรดทราบว่าหากคุณต้องการให้รหัสนี้ทำงานอย่างถูกต้องการเข้ารหัสอักขระจะต้องเปลี่ยนเป็นหนึ่งที่รองรับอักขระทั้งสองตัวเช่นการเข้ารหัส Unicode ทั้งหมด (UTF-8, UTF-16 (ใน BE หรือ LE), UTF-32, แม้แต่ UTF-7 ) หรือ Windows-1251, ISO 8859-5, KOI8-R (ขอบคุณ - Thomas WellerและPaŭlo Ebermann - สำหรับการชี้ให้เห็น):

public class A {
    public static void main(String[] args) {
        int а = 0;
        int a = 1;
        if == 0 && a == 1) {
            System.out.println("Success!");
        }
    }
}

(ฉันหวังว่าคุณจะไม่ต้องจัดการกับปัญหาแบบนั้นตลอดเวลาในอนาคต)


@Michael คุณหมายถึงอะไรที่ไม่ปรากฏขึ้นมาอย่างดี? ฉันเขียนมันลงในโทรศัพท์มือถือแล้วที่นี่มันก็โอเคกับฉันแม้ว่าจะเปลี่ยนเป็นมุมมองเดสก์ท็อปก็ตาม ถ้ามันจะทำให้คำตอบของฉันดีขึ้นโปรดแก้ไขให้ tuo ให้ชัดเจนเพราะฉันพบว่ามันยากไปหน่อย
Przemysław Moskal

@Michael ขอบคุณมาก ฉันคิดว่าสิ่งที่ฉันยอมรับในตอนท้ายของคำตอบของฉันก็พอ :)
Przemysław Moskal

@mohsenmadi ใช่ฉันไม่สามารถตรวจสอบได้ที่นี่บนโทรศัพท์มือถือ แต่ฉันค่อนข้างแน่ใจว่าก่อนที่จะแก้ไขประโยคสุดท้ายเกี่ยวกับการใช้ภาษาต่าง ๆ ในตัวอย่างของฉัน: P
Przemysław Moskal

ทำไม█ == 0 จึงคล้ายกับ == 1
โธมัสเวลเลอร์

1
nitpicking เพิ่มเติม: คุณไม่จำเป็นต้องใช้ UTF-8 (แม้ว่าจะเป็นสิ่งที่แนะนำก็ตาม) การเข้ารหัสอักขระใด ๆ ที่มีทั้งสองอย่างаและใช้aงานได้ตราบใดที่คุณบอกบรรณาธิการของคุณว่าการเข้ารหัสนั้นอยู่ใน (และอาจจะเป็นคอมไพเลอร์ด้วย) การเข้ารหัส Unicode ทั้งหมดทำงาน (UTF-8, UTF-16 (เป็น BE หรือ LE), UTF-32, แม้แต่ UTF-7), เช่นเดียวกับ Windows-1251, ISO 8859-5, KOI8-R
Paŭlo Ebermann

27

มีอีกวิธีหนึ่งในการเข้าถึงสิ่งนี้ (เพิ่มเติมจากแนวทางการแข่งขันข้อมูลที่ฉันโพสต์ไว้ก่อนหน้านี้) โดยใช้พลังของ PowerMock PowerMock ช่วยให้วิธีการที่จะถูกแทนที่ด้วยการใช้งานอื่น ๆ เมื่อรวมกับการแกะกล่องอัตโนมัตินิพจน์ต้นฉบับ(a == 1 && a == 2 && a == 3)ไม่มีการดัดแปลงสามารถทำให้เป็นจริงได้

คำตอบของ @ phflack ขึ้นอยู่กับการปรับเปลี่ยนกระบวนการมวยอัตโนมัติใน Java ที่ใช้การInteger.valueOf(...)โทร วิธีการด้านล่างนี้อาศัยการปรับแก้การแกะกล่องอัตโนมัติโดยเปลี่ยนการInteger.intValue()โทร

ข้อดีของวิธีการด้านล่างนี้คือการใช้คำสั่ง if ที่ได้รับจาก OP ในคำถามนั้นไม่มีการเปลี่ยนแปลงซึ่งฉันคิดว่าดีที่สุด

import static org.powermock.api.support.membermodification.MemberMatcher.method;
import static org.powermock.api.support.membermodification.MemberModifier.replace;

import java.util.concurrent.atomic.AtomicInteger;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@PrepareForTest(Integer.class)
@RunWith(PowerMockRunner.class)
public class Ais123 {
    @Before
    public void before() {
        // "value" is just a place to store an incrementing integer
        AtomicInteger value = new AtomicInteger(1);
        replace(method(Integer.class, "intValue"))
            .with((proxy, method, args) -> value.getAndIncrement());
    }

    @Test
    public void test() {
        Integer a = 1;

        if (a == 1 && a == 2 && a == 3) {
            System.out.println("Success");
        } else {
            Assert.fail("(a == 1 && a == 2 && a == 3) != true, a = " + a.intValue());
        }
    }

}

Powermock สามารถแทนที่วิธีสังเคราะห์เช่นaccess$nnnวิธีที่ใช้อ่านprivateฟิลด์ของคลาสภายใน / ภายนอกได้หรือไม่ ที่จะช่วยให้บางสายพันธุ์ที่น่าสนใจอื่น ๆ (ซึ่งได้ทำงานกับintตัวแปร) ...
โฮล

@ ความคิดที่น่าสนใจ Holger ฉันเห็นสิ่งที่คุณหมายถึง มันยังไม่ทำงาน - ไม่ชัดเจนว่ามีอะไรหยุดทำงาน
Erwin Bolwidt

ดีจริง ๆ นั่นคือสิ่งที่ฉันพยายามทำ แต่ฉันพบว่าการเปลี่ยนวิธีการคงที่จากคลาสที่ไม่เปลี่ยนรูปจะค่อนข้างยากโดยไม่ต้องจัดการกับ bytecode ดูเหมือนว่าฉันผิดไม่เคยได้ยิน PowerMock มาก่อน แต่ฉันสงสัยว่ามันทำอย่างนั้นได้อย่างไร ในฐานะที่เป็นหมายเหตุด้านคำตอบของ phflack ไม่ได้อาศัยการ autoboxing: เขาเปลี่ยน adresses ของ crypt Integer (ดังนั้น == จริง ๆ แล้วการเปรียบเทียบวัตถุที่อยู่ใน Integer มากกว่าค่า
Asoub

2
@ Asoub the casting ( (Integer)2) หล่อหลอมint มองมากยิ่งขึ้นในการสะท้อน , ดูเหมือนว่ามันเป็นไปไม่ได้ที่จะทำเช่นนี้กับ unboxing ใช้สะท้อน แต่อาจจะเป็นไปได้ด้วยการวัดแทน(หรือกับ PowerMock เช่นเดียวกับในคำตอบนี้)
phflack

@ Holger มันอาจจะไม่ขัดขวางวิธีสังเคราะห์แม้ว่ามันจะช่วยให้ฉันสามารถลงทะเบียนแทนaccess$0และการดำรงอยู่ของวิธีการที่มีการตรวจสอบที่ลงทะเบียน แต่การเปลี่ยนจะไม่ถูกเรียกใช้
Erwin Bolwidt

17

เนื่องจากสิ่งนี้ดูเหมือนว่าจะเป็นการติดตามคำถาม JavaScript นี้จึงเป็นเรื่องที่น่าสังเกตว่าเคล็ดลับนี้และงานที่คล้ายกันใน Java เช่นกัน:

public class Q48383521 {
    public static void main(String[] args) {
        int a = 1;
        int 2 = 3;
        int a = 3;
        if(aᅠ==1 && a==ᅠ2 && a==3) {
            System.out.println("success");
        }
    }
}

บน Ideone


แต่โปรดทราบว่านี่ไม่ใช่สิ่งที่แย่ที่สุดที่คุณสามารถทำได้กับ Unicode การใช้ white-space หรืออักขระควบคุมที่เป็นส่วนของตัวระบุที่ถูกต้องหรือใช้ตัวอักษรต่าง ๆ ที่มีลักษณะเหมือนเดิมยังคงสร้างตัวระบุที่แตกต่างและสามารถเห็นได้เช่นเมื่อทำการค้นหาข้อความ

แต่โปรแกรมนี้

public class Q48383521 {
    public static void main(String[] args) {
        int ä = 1;
        int ä = 2;
        if(ä == 1 && ä == 2) {
            System.out.println("success");
        }
    }
}

ใช้ตัวระบุสองตัวที่เหมือนกันอย่างน้อยจากมุมมอง Unicode พวกเขาเพียงแค่ใช้วิธีการที่แตกต่างกันในการเข้ารหัสตัวอักษรเดียวกันäโดยใช้และU+00E4U+0061 U+0308

บน Ideone

เครื่องมือเหล่านี้อาจไม่เหมือนกันเครื่องมือข้อความที่เปิดใช้งาน Unicode อาจไม่ได้รายงานความแตกต่างใด ๆ ขึ้นอยู่กับเครื่องมือที่คุณใช้ คุณอาจมีปัญหาที่การรับรองที่แตกต่างกันหายไปเมื่อคัดลอกซอร์สโค้ดไปยังบุคคลอื่นบางทีพยายามขอความช่วยเหลือสำหรับ“ พฤติกรรมแปลก ๆ ” ทำให้ไม่สามารถทำซ้ำได้สำหรับผู้ช่วย


3
เอ๊ะคำตอบนี้ไม่ครอบคลุมถึงการทำผิดกฎยูนิโค้ดได้ดีพอใช่ไหม
Michael

2
int ᅠ2 = 3;มันตั้งใจหรือไม่ เพราะฉันเห็นโค้ดแปลก ๆ อยู่รอบตัว
Ravi

1
@Michael ไม่ถูกต้องเนื่องจากคำตอบนั้นเกี่ยวกับการใช้ตัวอักษรสองตัวที่แตกต่างกัน (ซึ่ง IDEs จะพิจารณาแตกต่างกันเมื่อค้นหาa) ในขณะที่นี่เป็นพื้นที่สีขาวและก็ให้เครดิตกับคำตอบที่เก่ากว่าสำหรับคำถาม JavaScript ที่เกี่ยวข้อง โปรดทราบว่าความคิดเห็นของฉันมีแม้จะเก่ากว่าคำถาม Java (โดยหลายวัน) ...
โฮล

2
ฉันไม่เห็นความแตกต่าง คำตอบทั้งสองนี้จะให้วิธีการแก้ปัญหาที่ตัวระบุสามตัวในคำสั่ง if คล้ายกัน แต่มีความแตกต่างทางเทคนิคโดยอาศัยการใช้อักขระ Unicode ที่ผิดปกติ ไม่ว่าจะเป็นช่องว่างหรือ Cyrillic นั้นไม่เกี่ยวข้อง
Michael

2
@Michael คุณอาจเห็นว่าเป็นอย่างนั้นนั่นก็ขึ้นอยู่กับคุณ ดังที่ได้กล่าวไว้ฉันต้องการระบุว่าคำตอบที่ให้ไว้เมื่อห้าวันที่แล้วสำหรับ JavaScript นั้นใช้กับ Java ด้วยโดยพิจารณาจากประวัติของคำถาม ใช่มันค่อนข้างซ้ำซ้อนกับคำตอบอื่นซึ่งไม่ได้อ้างถึงคำถาม JavaScript ที่เชื่อมโยง อย่างไรก็ตามในขณะเดียวกันฉันได้อัปเดตคำตอบของฉันเพื่อเพิ่มเคสที่ไม่เกี่ยวกับตัวละครที่คล้ายกันทางสายตา แต่วิธีต่าง ๆ ในการเข้ารหัสตัวละครเดียวกันและมันก็ไม่ได้เป็น มันเป็นตัวละครที่ผมใช้ทุกวัน ...
โฮล

4

แรงบันดาลใจจาก @ ยอดเยี่ยมของเออร์วินคำตอบที่ผมเขียนเป็นตัวอย่างที่คล้ายกัน แต่ใช้ Java กระแส API

และสิ่งที่น่าสนใจคือโซลูชันของฉันใช้งานได้ แต่ในบางกรณีที่หายากมาก (เพราะ   just-in-timeคอมไพเลอร์ปรับรหัสให้เหมาะสม)

เคล็ดลับคือการปิดใช้งานJITการเพิ่มประสิทธิภาพโดยใช้VMตัวเลือกต่อไปนี้:

-Djava.compiler=NONE

ในสถานการณ์นี้จำนวนกรณีความสำเร็จเพิ่มขึ้นอย่างมีนัยสำคัญ นี่คือรหัส:

class Race {
    private static int a;

    public static void main(String[] args) {
        IntStream.range(0, 100_000).parallel().forEach(i -> {
            a = 1;
            a = 2;
            a = 3;
            testValue();
        });
    }

    private static void testValue() {
        if (a == 1 && a == 2 && a == 3) {
            System.out.println("Success");
        }
    }
}

PS Parallel stream ใช้ForkJoinPoolภายใต้ประทุนและตัวแปรaถูกแชร์ระหว่างหลายเธรดโดยไม่มีการซิงโครไนซ์ใด ๆ นั่นเป็นสาเหตุที่ผลลัพธ์ไม่ได้กำหนดไว้


1

ตามเส้นที่คล้ายกันโดยบังคับให้มีการลอย (หรือสองครั้ง) เพื่อ underflow (หรือล้น) ผ่านการหาร (หรือการคูณ) ด้วยจำนวนมาก:

int a = 1;
if (a / Float.POSITIVE_INFINITY == 1 / Float.POSITIVE_INFINITY
        && a / Float.POSITIVE_INFINITY == 2 / Float.POSITIVE_INFINITY
        && a / Float.POSITIVE_INFINITY == 3 / Float.POSITIVE_INFINITY) {
    System.out.println("Success");
}

2
@PatrickRoberts - พฤติกรรมที่เฉพาะเจาะจงนี้จะลอย underflow จุดตามเอกสาร Java ยังเห็นนี้ , นี้ , นี้และนี้
Aloke
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.