Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6180437
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 24, 20262026-05-24T00:50:40+00:00 2026-05-24T00:50:40+00:00

After many hours of debugging and analysis, I have finally managed to isolate the

  • 0

After many hours of debugging and analysis, I have finally managed to isolate the cause of a race condition. Solving it is another matter!

To see the race condition in action, I recorded a video some way in to the debugging process. I have since furthered my understanding of the situation so please forgive the poor commentary and the silly mechanisms implemented as part of the debugging process.

http://screencast.com/t/aTAk1NOVanjR

So, the situation: we have a double buffered implementation of a surface (i.e. java.awt.Frame or Window) where there is an ongoing thread that essentially loops continuously, invoking the render process (which performs UI layout and renders it to the backbuffer) and then, post-render, blits the rendered area from backbuffer to screen.

Here’s the pseudo-code version (full version line 824 of Surface.java) of the double buffered render:

public RenderedRegions render() {
    // pseudo code
    RenderedRegions r = super.render();
    if (r==null) // nothing rendered
        return
    for (region in r)
        establish max bounds
    blit(max bounds)
    return r;
}

As with any AWT surface implementation, it also implements (line 507 in AWT.java – link limit 🙁 – use Surface.java link, replace core/Surface.java with plat/AWT.java) the paint/update overrides which also blit from the backbuffer to the screen:

        public void paint(Graphics gr) {
            Rectangle r = gr.getClipBounds();
            refreshFromBackbuffer(r.x - leftInset, r.y - topInset, r.width, r.height);
        }

Blitting is implemented (line 371 in AWT.java) using the drawImage() function:

    /** synchronized as otherwise it is possible to blit before images have been rendered to the backbuffer */
    public synchronized void blit(PixelBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2) {
        discoverInsets();
        try {
            window.getGraphics().drawImage(((AWTPixelBuffer)s).i,
                              dx + leftInset, dy + topInset,     // destination topleft corner
                              dx2 + leftInset, dy2 + topInset,   // destination bottomright corner
                              sx, sy,                            // source topleft corner
                              sx + (dx2 - dx), sy + (dy2 - dy),  // source bottomright corner
                              null);
        } catch (NullPointerException npe) { /* FIXME: handle this gracefully */ }
    }

(Warning: this is where I start making assumptions!)

The problem here seems to be that drawImage is asynchronous and that a blit from refreshBackBuffer() via paint/update is called first but occurs second.

So… blit is already synchronized. The obvious way of preventing the race condition doesn’t work. 🙁

So far I have come up with two solutions, but neither of them are ideal:

  1. re-blit on the next render pass
    cons: performance hit, still get a bit of flicker due when encountering the race condition (valid screen -> invalid screen -> valid screen)

  2. do not blit on paint/update, instead set refresh bounds and use those bounds on next render pass
    cons: get black flicker when the screen is invalidated and the main application thread is catching up

Here (1) seems to be the lesser of two evils. Edit: and (2) doesn’t work, getting blank screens… (1) works fine but is just masking the problem which is potentially still there.

What I’m hoping for, and seem unable to conjure up due to my weak understanding of synchronized and how to use it, is a locking mechanism that somehow accounts for the asynchronous nature of drawImage().

Or perhaps use ImageObserver?

Note that due to the nature of the application (Vexi, for those interested, website is out of date and I can only use 2 hyperlinks) the render thread must be outside of paint/update – it has a single-threaded script model and the layout process (a sub-process of render) invokes script.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-24T00:50:41+00:00Added an answer on May 24, 2026 at 12:50 am

    Update: good approach here: AWT custom rendering – capture smooth resizes and eliminate resize flicker


    The answer here was to remove all blitting from the paint() thread i.e. only ever refresh from the backbuffer in the program thread. This is the opposite to the answer as suggested by Jochen Bedersdorfer, but his answer was never going to work for us because the program has its own scripting model that is integrated with the layout model which drives rendering, thus it all has to happen sequentially.

    (Speculation) Some of the problems stem from a less-than-stellar multiple monitor support in Java with accelerated graphics chipsets, as I ran in to this problem when adapting to use BufferStrategy, which was a direct3d+Java discrepancy.

    Essentially paint() and update() are reduced to blocking calls. This works a lot better but has one drawback – there is no smooth resizing.

    private class InnerFrame extends Frame() {
        public void update(Graphics g) { }
        public void paint(Graphics g) { }
        ....
    }
    

    I ended up using a buffer strategy although I’m not 100% satisfied with this approach as it seems to me that it is inefficient to be rendering to an image, then copying the full image to the BufferStrategy and then performing a show() to screen.

    I also implemented a Swing-based alternative, but again I don’t particularly like that. It uses a JLabel with an ImageIcon, whereby the program thread (not the EDT) draws to the Image that is wrapped by the ImageIcon.

    I’m sure there’s a follow up question for me to ask when I have more time to look into this with more purpose, but for now I have two working implementations that more or less address the initial woes as posted here – and I learnt a helluva lot discovering them.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

After many hours, I finally realize that I am working correctly with the Cache
After many hours, I have discovered that the given udp server needs the following
After many, many hours I managed to figure out how to share cookies betwen
Trying to parse an nested expressions like GroupParser.parse({{a}{{c}{d}}}) After many hours i have now
after many hours and starting from similar layout that already worked I have almost
After googling for many hours for a solution for the above Sharepoint exception, I
After many hair-pulling frustrations I've finally got one version of the PerlMagick module working
I have what I know is a simple question, but after many searches in
After many months of postponing it, this week, I finally started using a new
I am writing a custom textfile-data parser (JSON-like) and I have lost many hours

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.